libv8 8.4.255.0

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 (639) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +45 -0
  6. data/CHANGELOG.md +111 -0
  7. data/Gemfile +4 -0
  8. data/README.md +152 -0
  9. data/Rakefile +125 -0
  10. data/appveyor.yml.disabled +36 -0
  11. data/ext/libv8/arch.rb +20 -0
  12. data/ext/libv8/builder.rb +106 -0
  13. data/ext/libv8/extconf.rb +7 -0
  14. data/ext/libv8/location.rb +89 -0
  15. data/ext/libv8/paths.rb +28 -0
  16. data/lib/libv8.rb +9 -0
  17. data/lib/libv8/version.rb +3 -0
  18. data/libv8.gemspec +30 -0
  19. data/scaleway.png +0 -0
  20. data/spec/location_spec.rb +69 -0
  21. data/spec/spec_helper.rb +4 -0
  22. data/thefrontside.png +0 -0
  23. data/vendor/depot_tools/.cipd_impl.ps1 +129 -0
  24. data/vendor/depot_tools/.gitattributes +55 -0
  25. data/vendor/depot_tools/.gitignore +92 -0
  26. data/vendor/depot_tools/.style.yapf +4 -0
  27. data/vendor/depot_tools/.vpython +55 -0
  28. data/vendor/depot_tools/.vpython3 +23 -0
  29. data/vendor/depot_tools/CROS_OWNERS +7 -0
  30. data/vendor/depot_tools/GOMA_OWNERS +9 -0
  31. data/vendor/depot_tools/LICENSE +27 -0
  32. data/vendor/depot_tools/LUCI_OWNERS +5 -0
  33. data/vendor/depot_tools/OWNERS +39 -0
  34. data/vendor/depot_tools/PRESUBMIT.py +150 -0
  35. data/vendor/depot_tools/README.gclient.md +67 -0
  36. data/vendor/depot_tools/README.git-cl.md +99 -0
  37. data/vendor/depot_tools/README.md +78 -0
  38. data/vendor/depot_tools/WATCHLISTS +26 -0
  39. data/vendor/depot_tools/auth.py +163 -0
  40. data/vendor/depot_tools/autoninja +36 -0
  41. data/vendor/depot_tools/autoninja.bat +33 -0
  42. data/vendor/depot_tools/autoninja.py +148 -0
  43. data/vendor/depot_tools/bb +12 -0
  44. data/vendor/depot_tools/bb.bat +7 -0
  45. data/vendor/depot_tools/bootstrap/README.md +155 -0
  46. data/vendor/depot_tools/bootstrap/bootstrap.py +356 -0
  47. data/vendor/depot_tools/bootstrap/git-bash.template.sh +12 -0
  48. data/vendor/depot_tools/bootstrap/git.template.bat +5 -0
  49. data/vendor/depot_tools/bootstrap/manifest.txt +27 -0
  50. data/vendor/depot_tools/bootstrap/manifest_bleeding_edge.txt +27 -0
  51. data/vendor/depot_tools/bootstrap/profile.d.python.sh +20 -0
  52. data/vendor/depot_tools/bootstrap/python27.bat +46 -0
  53. data/vendor/depot_tools/bootstrap/python3.bat +46 -0
  54. data/vendor/depot_tools/bootstrap/win_tools.bat +79 -0
  55. data/vendor/depot_tools/bootstrap_python3 +35 -0
  56. data/vendor/depot_tools/breakpad.py +12 -0
  57. data/vendor/depot_tools/cbuildbot +1 -0
  58. data/vendor/depot_tools/chrome_set_ver +1 -0
  59. data/vendor/depot_tools/cipd +247 -0
  60. data/vendor/depot_tools/cipd.bat +67 -0
  61. data/vendor/depot_tools/cipd_bin_setup.bat +6 -0
  62. data/vendor/depot_tools/cipd_bin_setup.sh +22 -0
  63. data/vendor/depot_tools/cipd_client_version +1 -0
  64. data/vendor/depot_tools/cipd_client_version.digests +22 -0
  65. data/vendor/depot_tools/cipd_manifest.txt +63 -0
  66. data/vendor/depot_tools/cipd_manifest.versions +438 -0
  67. data/vendor/depot_tools/cit +8 -0
  68. data/vendor/depot_tools/cit.bat +12 -0
  69. data/vendor/depot_tools/cit.py +167 -0
  70. data/vendor/depot_tools/clang-format +8 -0
  71. data/vendor/depot_tools/clang-format.bat +12 -0
  72. data/vendor/depot_tools/clang_format.py +79 -0
  73. data/vendor/depot_tools/clang_format_merge_driver +8 -0
  74. data/vendor/depot_tools/clang_format_merge_driver.bat +12 -0
  75. data/vendor/depot_tools/clang_format_merge_driver.py +69 -0
  76. data/vendor/depot_tools/codereview.settings +6 -0
  77. data/vendor/depot_tools/compile_single_file +8 -0
  78. data/vendor/depot_tools/compile_single_file.bat +11 -0
  79. data/vendor/depot_tools/compile_single_file.py +79 -0
  80. data/vendor/depot_tools/cpplint.bat +11 -0
  81. data/vendor/depot_tools/cpplint.py +6097 -0
  82. data/vendor/depot_tools/cpplint_chromium.py +50 -0
  83. data/vendor/depot_tools/cros +87 -0
  84. data/vendor/depot_tools/cros_sdk +1 -0
  85. data/vendor/depot_tools/crosjobs +13 -0
  86. data/vendor/depot_tools/detect_host_arch.py +55 -0
  87. data/vendor/depot_tools/dirmd +12 -0
  88. data/vendor/depot_tools/dirmd.bat +7 -0
  89. data/vendor/depot_tools/download_from_google_storage +8 -0
  90. data/vendor/depot_tools/download_from_google_storage.bat +12 -0
  91. data/vendor/depot_tools/download_from_google_storage.py +634 -0
  92. data/vendor/depot_tools/ensure_bootstrap +53 -0
  93. data/vendor/depot_tools/fetch +21 -0
  94. data/vendor/depot_tools/fetch.bat +28 -0
  95. data/vendor/depot_tools/fetch.py +319 -0
  96. data/vendor/depot_tools/fetch_configs/android.py +34 -0
  97. data/vendor/depot_tools/fetch_configs/android_internal.py +34 -0
  98. data/vendor/depot_tools/fetch_configs/breakpad.py +44 -0
  99. data/vendor/depot_tools/fetch_configs/chromium.py +66 -0
  100. data/vendor/depot_tools/fetch_configs/config_util.py +52 -0
  101. data/vendor/depot_tools/fetch_configs/crashpad.py +41 -0
  102. data/vendor/depot_tools/fetch_configs/dart.py +45 -0
  103. data/vendor/depot_tools/fetch_configs/depot_tools.py +44 -0
  104. data/vendor/depot_tools/fetch_configs/devtools-frontend.py +44 -0
  105. data/vendor/depot_tools/fetch_configs/goma_client.py +41 -0
  106. data/vendor/depot_tools/fetch_configs/gyp.py +41 -0
  107. data/vendor/depot_tools/fetch_configs/infra.py +40 -0
  108. data/vendor/depot_tools/fetch_configs/infra_internal.py +45 -0
  109. data/vendor/depot_tools/fetch_configs/inspector_protocol.py +40 -0
  110. data/vendor/depot_tools/fetch_configs/ios.py +34 -0
  111. data/vendor/depot_tools/fetch_configs/ios_internal.py +39 -0
  112. data/vendor/depot_tools/fetch_configs/nacl.py +48 -0
  113. data/vendor/depot_tools/fetch_configs/naclports.py +47 -0
  114. data/vendor/depot_tools/fetch_configs/node-ci.py +41 -0
  115. data/vendor/depot_tools/fetch_configs/pdfium.py +40 -0
  116. data/vendor/depot_tools/fetch_configs/skia.py +41 -0
  117. data/vendor/depot_tools/fetch_configs/skia_buildbot.py +41 -0
  118. data/vendor/depot_tools/fetch_configs/syzygy.py +41 -0
  119. data/vendor/depot_tools/fetch_configs/v8.py +44 -0
  120. data/vendor/depot_tools/fetch_configs/webrtc.py +52 -0
  121. data/vendor/depot_tools/fetch_configs/webrtc_android.py +34 -0
  122. data/vendor/depot_tools/fetch_configs/webrtc_ios.py +34 -0
  123. data/vendor/depot_tools/fix_encoding.py +385 -0
  124. data/vendor/depot_tools/gclient +38 -0
  125. data/vendor/depot_tools/gclient-new-workdir.py +124 -0
  126. data/vendor/depot_tools/gclient.bat +32 -0
  127. data/vendor/depot_tools/gclient.py +3198 -0
  128. data/vendor/depot_tools/gclient_completion.sh +76 -0
  129. data/vendor/depot_tools/gclient_eval.py +891 -0
  130. data/vendor/depot_tools/gclient_paths.py +152 -0
  131. data/vendor/depot_tools/gclient_scm.py +1615 -0
  132. data/vendor/depot_tools/gclient_utils.py +1280 -0
  133. data/vendor/depot_tools/gerrit_client.py +151 -0
  134. data/vendor/depot_tools/gerrit_util.py +996 -0
  135. data/vendor/depot_tools/git-cache +6 -0
  136. data/vendor/depot_tools/git-cl +6 -0
  137. data/vendor/depot_tools/git-crrev-parse +53 -0
  138. data/vendor/depot_tools/git-drover +6 -0
  139. data/vendor/depot_tools/git-find-releases +6 -0
  140. data/vendor/depot_tools/git-footers +6 -0
  141. data/vendor/depot_tools/git-freeze +8 -0
  142. data/vendor/depot_tools/git-gs +9 -0
  143. data/vendor/depot_tools/git-hyper-blame +6 -0
  144. data/vendor/depot_tools/git-map +6 -0
  145. data/vendor/depot_tools/git-map-branches +6 -0
  146. data/vendor/depot_tools/git-mark-merge-base +6 -0
  147. data/vendor/depot_tools/git-nav-downstream +6 -0
  148. data/vendor/depot_tools/git-nav-upstream +6 -0
  149. data/vendor/depot_tools/git-new-branch +6 -0
  150. data/vendor/depot_tools/git-number +6 -0
  151. data/vendor/depot_tools/git-rebase-update +6 -0
  152. data/vendor/depot_tools/git-rename-branch +6 -0
  153. data/vendor/depot_tools/git-reparent-branch +6 -0
  154. data/vendor/depot_tools/git-retry +8 -0
  155. data/vendor/depot_tools/git-runhooks +23 -0
  156. data/vendor/depot_tools/git-squash-branch +6 -0
  157. data/vendor/depot_tools/git-templates/description +3 -0
  158. data/vendor/depot_tools/git-templates/hooks/applypatch-msg +4 -0
  159. data/vendor/depot_tools/git-templates/hooks/post-applypatch +4 -0
  160. data/vendor/depot_tools/git-templates/hooks/post-checkout +4 -0
  161. data/vendor/depot_tools/git-templates/hooks/post-commit +4 -0
  162. data/vendor/depot_tools/git-templates/hooks/post-merge +4 -0
  163. data/vendor/depot_tools/git-templates/hooks/post-update +4 -0
  164. data/vendor/depot_tools/git-templates/hooks/pre-applypatch +4 -0
  165. data/vendor/depot_tools/git-templates/hooks/pre-auto-gc +4 -0
  166. data/vendor/depot_tools/git-templates/hooks/pre-commit +4 -0
  167. data/vendor/depot_tools/git-templates/hooks/pre-rebase +4 -0
  168. data/vendor/depot_tools/git-templates/hooks/prepare-commit-msg +4 -0
  169. data/vendor/depot_tools/git-templates/info/exclude +6 -0
  170. data/vendor/depot_tools/git-thaw +13 -0
  171. data/vendor/depot_tools/git-upstream-diff +9 -0
  172. data/vendor/depot_tools/git_cache.py +786 -0
  173. data/vendor/depot_tools/git_cl.py +5158 -0
  174. data/vendor/depot_tools/git_cl_completion.sh +48 -0
  175. data/vendor/depot_tools/git_common.py +1101 -0
  176. data/vendor/depot_tools/git_dates.py +62 -0
  177. data/vendor/depot_tools/git_drover.py +469 -0
  178. data/vendor/depot_tools/git_find_releases.py +67 -0
  179. data/vendor/depot_tools/git_footers.py +261 -0
  180. data/vendor/depot_tools/git_freezer.py +40 -0
  181. data/vendor/depot_tools/git_hyper_blame.py +391 -0
  182. data/vendor/depot_tools/git_map.py +166 -0
  183. data/vendor/depot_tools/git_map_branches.py +354 -0
  184. data/vendor/depot_tools/git_mark_merge_base.py +73 -0
  185. data/vendor/depot_tools/git_nav_downstream.py +69 -0
  186. data/vendor/depot_tools/git_new_branch.py +82 -0
  187. data/vendor/depot_tools/git_number.py +301 -0
  188. data/vendor/depot_tools/git_rebase_update.py +351 -0
  189. data/vendor/depot_tools/git_rename_branch.py +55 -0
  190. data/vendor/depot_tools/git_reparent_branch.py +101 -0
  191. data/vendor/depot_tools/git_retry.py +181 -0
  192. data/vendor/depot_tools/git_squash_branch.py +28 -0
  193. data/vendor/depot_tools/git_upstream_diff.py +64 -0
  194. data/vendor/depot_tools/gn +8 -0
  195. data/vendor/depot_tools/gn.bat +12 -0
  196. data/vendor/depot_tools/gn.py +78 -0
  197. data/vendor/depot_tools/goma_auth +12 -0
  198. data/vendor/depot_tools/goma_auth.bat +8 -0
  199. data/vendor/depot_tools/goma_ctl +12 -0
  200. data/vendor/depot_tools/goma_ctl.bat +8 -0
  201. data/vendor/depot_tools/gsutil.py +190 -0
  202. data/vendor/depot_tools/gsutil.py.bat +23 -0
  203. data/vendor/depot_tools/gsutil.vpython +120 -0
  204. data/vendor/depot_tools/infra/README.md +1 -0
  205. data/vendor/depot_tools/infra/config/OWNERS +7 -0
  206. data/vendor/depot_tools/infra/config/README.md +1 -0
  207. data/vendor/depot_tools/infra/config/recipes.cfg +26 -0
  208. data/vendor/depot_tools/led +12 -0
  209. data/vendor/depot_tools/led.bat +7 -0
  210. data/vendor/depot_tools/lockfile.py +116 -0
  211. data/vendor/depot_tools/luci-auth +13 -0
  212. data/vendor/depot_tools/luci-auth.bat +8 -0
  213. data/vendor/depot_tools/lucicfg +12 -0
  214. data/vendor/depot_tools/lucicfg.bat +7 -0
  215. data/vendor/depot_tools/mac_toolchain +12 -0
  216. data/vendor/depot_tools/man/html/depot_tools.html +934 -0
  217. data/vendor/depot_tools/man/html/depot_tools_tutorial.html +1593 -0
  218. data/vendor/depot_tools/man/html/git-cl.html +1033 -0
  219. data/vendor/depot_tools/man/html/git-drover.html +1048 -0
  220. data/vendor/depot_tools/man/html/git-footers.html +878 -0
  221. data/vendor/depot_tools/man/html/git-freeze.html +859 -0
  222. data/vendor/depot_tools/man/html/git-hyper-blame.html +878 -0
  223. data/vendor/depot_tools/man/html/git-map-branches.html +904 -0
  224. data/vendor/depot_tools/man/html/git-map.html +887 -0
  225. data/vendor/depot_tools/man/html/git-mark-merge-base.html +826 -0
  226. data/vendor/depot_tools/man/html/git-nav-downstream.html +844 -0
  227. data/vendor/depot_tools/man/html/git-nav-upstream.html +853 -0
  228. data/vendor/depot_tools/man/html/git-new-branch.html +932 -0
  229. data/vendor/depot_tools/man/html/git-rebase-update.html +961 -0
  230. data/vendor/depot_tools/man/html/git-rename-branch.html +794 -0
  231. data/vendor/depot_tools/man/html/git-reparent-branch.html +847 -0
  232. data/vendor/depot_tools/man/html/git-retry.html +858 -0
  233. data/vendor/depot_tools/man/html/git-squash-branch.html +881 -0
  234. data/vendor/depot_tools/man/html/git-thaw.html +794 -0
  235. data/vendor/depot_tools/man/html/git-upstream-diff.html +923 -0
  236. data/vendor/depot_tools/man/man1/git-cl.1 +198 -0
  237. data/vendor/depot_tools/man/man1/git-drover.1 +330 -0
  238. data/vendor/depot_tools/man/man1/git-footers.1 +144 -0
  239. data/vendor/depot_tools/man/man1/git-freeze.1 +113 -0
  240. data/vendor/depot_tools/man/man1/git-hyper-blame.1 +128 -0
  241. data/vendor/depot_tools/man/man1/git-map-branches.1 +210 -0
  242. data/vendor/depot_tools/man/man1/git-map.1 +179 -0
  243. data/vendor/depot_tools/man/man1/git-mark-merge-base.1 +69 -0
  244. data/vendor/depot_tools/man/man1/git-nav-downstream.1 +112 -0
  245. data/vendor/depot_tools/man/man1/git-nav-upstream.1 +122 -0
  246. data/vendor/depot_tools/man/man1/git-new-branch.1 +176 -0
  247. data/vendor/depot_tools/man/man1/git-rebase-update.1 +177 -0
  248. data/vendor/depot_tools/man/man1/git-rename-branch.1 +53 -0
  249. data/vendor/depot_tools/man/man1/git-reparent-branch.1 +93 -0
  250. data/vendor/depot_tools/man/man1/git-retry.1 +108 -0
  251. data/vendor/depot_tools/man/man1/git-squash-branch.1 +129 -0
  252. data/vendor/depot_tools/man/man1/git-thaw.1 +54 -0
  253. data/vendor/depot_tools/man/man1/git-upstream-diff.1 +153 -0
  254. data/vendor/depot_tools/man/man7/depot_tools.7 +139 -0
  255. data/vendor/depot_tools/man/man7/depot_tools_tutorial.7 +1061 -0
  256. data/vendor/depot_tools/man/push_to_gs.sh +4 -0
  257. data/vendor/depot_tools/man/src/.gitignore +5 -0
  258. data/vendor/depot_tools/man/src/_aliases.txt +5 -0
  259. data/vendor/depot_tools/man/src/_footer.txt +8 -0
  260. data/vendor/depot_tools/man/src/_git-cl_desc.helper.txt +1 -0
  261. data/vendor/depot_tools/man/src/_git-drover_desc.helper.txt +2 -0
  262. data/vendor/depot_tools/man/src/_git-footers_desc.helper.txt +1 -0
  263. data/vendor/depot_tools/man/src/_git-freeze_desc.helper.txt +1 -0
  264. data/vendor/depot_tools/man/src/_git-hyper-blame_desc.helper.txt +1 -0
  265. data/vendor/depot_tools/man/src/_git-map-branches_desc.helper.txt +4 -0
  266. data/vendor/depot_tools/man/src/_git-map_desc.helper.txt +3 -0
  267. data/vendor/depot_tools/man/src/_git-mark-merge-base_desc.helper.txt +1 -0
  268. data/vendor/depot_tools/man/src/_git-nav-downstream_desc.helper.txt +1 -0
  269. data/vendor/depot_tools/man/src/_git-nav-upstream_desc.helper.txt +1 -0
  270. data/vendor/depot_tools/man/src/_git-new-branch_desc.helper.txt +1 -0
  271. data/vendor/depot_tools/man/src/_git-rebase-update_desc.helper.txt +1 -0
  272. data/vendor/depot_tools/man/src/_git-rename-branch_desc.helper.txt +1 -0
  273. data/vendor/depot_tools/man/src/_git-reparent-branch_desc.helper.txt +1 -0
  274. data/vendor/depot_tools/man/src/_git-retry_desc.helper.txt +2 -0
  275. data/vendor/depot_tools/man/src/_git-squash-branch_desc.helper.txt +1 -0
  276. data/vendor/depot_tools/man/src/_git-thaw_desc.helper.txt +2 -0
  277. data/vendor/depot_tools/man/src/_git-upstream-diff_desc.helper.txt +1 -0
  278. data/vendor/depot_tools/man/src/_helper_prefix.txt +1 -0
  279. data/vendor/depot_tools/man/src/asciidoc-override.css +7 -0
  280. data/vendor/depot_tools/man/src/common_demo_functions.sh +84 -0
  281. data/vendor/depot_tools/man/src/demo_repo.sh +43 -0
  282. data/vendor/depot_tools/man/src/depot_tools.txt +28 -0
  283. data/vendor/depot_tools/man/src/depot_tools_tutorial.demo.walkthrough.sh +155 -0
  284. data/vendor/depot_tools/man/src/depot_tools_tutorial.txt +432 -0
  285. data/vendor/depot_tools/man/src/filter_demo_output.py +141 -0
  286. data/vendor/depot_tools/man/src/git-cl.txt +119 -0
  287. data/vendor/depot_tools/man/src/git-drover.demo.1.sh +22 -0
  288. data/vendor/depot_tools/man/src/git-drover.demo.2.sh +23 -0
  289. data/vendor/depot_tools/man/src/git-drover.demo.3.sh +27 -0
  290. data/vendor/depot_tools/man/src/git-drover.demo.4.sh +39 -0
  291. data/vendor/depot_tools/man/src/git-drover.demo.common.sh +19 -0
  292. data/vendor/depot_tools/man/src/git-drover.txt +102 -0
  293. data/vendor/depot_tools/man/src/git-footers.demo.1.sh +17 -0
  294. data/vendor/depot_tools/man/src/git-footers.txt +71 -0
  295. data/vendor/depot_tools/man/src/git-freeze.demo.1.sh +23 -0
  296. data/vendor/depot_tools/man/src/git-freeze.txt +54 -0
  297. data/vendor/depot_tools/man/src/git-hyper-blame.demo.1.sh +3 -0
  298. data/vendor/depot_tools/man/src/git-hyper-blame.demo.2.sh +4 -0
  299. data/vendor/depot_tools/man/src/git-hyper-blame.demo.common.sh +57 -0
  300. data/vendor/depot_tools/man/src/git-hyper-blame.txt +85 -0
  301. data/vendor/depot_tools/man/src/git-map-branches.demo.1.sh +8 -0
  302. data/vendor/depot_tools/man/src/git-map-branches.txt +64 -0
  303. data/vendor/depot_tools/man/src/git-map.demo.1.sh +3 -0
  304. data/vendor/depot_tools/man/src/git-map.txt +67 -0
  305. data/vendor/depot_tools/man/src/git-mark-merge-base.txt +46 -0
  306. data/vendor/depot_tools/man/src/git-nav-downstream.demo.1.sh +12 -0
  307. data/vendor/depot_tools/man/src/git-nav-downstream.txt +40 -0
  308. data/vendor/depot_tools/man/src/git-nav-upstream.demo.1.sh +12 -0
  309. data/vendor/depot_tools/man/src/git-nav-upstream.txt +39 -0
  310. data/vendor/depot_tools/man/src/git-new-branch.demo.1.sh +17 -0
  311. data/vendor/depot_tools/man/src/git-new-branch.txt +82 -0
  312. data/vendor/depot_tools/man/src/git-rebase-update.txt +141 -0
  313. data/vendor/depot_tools/man/src/git-rename-branch.txt +28 -0
  314. data/vendor/depot_tools/man/src/git-reparent-branch.txt +61 -0
  315. data/vendor/depot_tools/man/src/git-retry.txt +67 -0
  316. data/vendor/depot_tools/man/src/git-squash-branch.demo.1.sh +12 -0
  317. data/vendor/depot_tools/man/src/git-squash-branch.txt +59 -0
  318. data/vendor/depot_tools/man/src/git-thaw.txt +29 -0
  319. data/vendor/depot_tools/man/src/git-upstream-diff.txt +107 -0
  320. data/vendor/depot_tools/man/src/make_docs.sh +260 -0
  321. data/vendor/depot_tools/man/src/prep_demo_repo.sh +103 -0
  322. data/vendor/depot_tools/metrics.README.md +101 -0
  323. data/vendor/depot_tools/metrics.py +297 -0
  324. data/vendor/depot_tools/metrics_utils.py +293 -0
  325. data/vendor/depot_tools/my_activity.py +971 -0
  326. data/vendor/depot_tools/ninja +44 -0
  327. data/vendor/depot_tools/ninja-linux32 +0 -0
  328. data/vendor/depot_tools/ninja-linux64 +0 -0
  329. data/vendor/depot_tools/ninja-mac +0 -0
  330. data/vendor/depot_tools/ninja.exe +0 -0
  331. data/vendor/depot_tools/ninjalog.README.md +64 -0
  332. data/vendor/depot_tools/ninjalog_uploader.py +233 -0
  333. data/vendor/depot_tools/ninjalog_uploader_wrapper.py +125 -0
  334. data/vendor/depot_tools/owners.py +641 -0
  335. data/vendor/depot_tools/owners_finder.py +385 -0
  336. data/vendor/depot_tools/post_build_ninja_summary.py +350 -0
  337. data/vendor/depot_tools/presubmit_canned_checks.py +1655 -0
  338. data/vendor/depot_tools/presubmit_support.py +1923 -0
  339. data/vendor/depot_tools/profile.xml +8 -0
  340. data/vendor/depot_tools/prpc +13 -0
  341. data/vendor/depot_tools/prpc.bat +8 -0
  342. data/vendor/depot_tools/pylint +9 -0
  343. data/vendor/depot_tools/pylint-1.5 +78 -0
  344. data/vendor/depot_tools/pylint-1.6 +78 -0
  345. data/vendor/depot_tools/pylint-1.7 +78 -0
  346. data/vendor/depot_tools/pylint-1.8 +78 -0
  347. data/vendor/depot_tools/pylint-1.9 +78 -0
  348. data/vendor/depot_tools/pylint.bat +12 -0
  349. data/vendor/depot_tools/pylint_main.py +45 -0
  350. data/vendor/depot_tools/pylintrc +349 -0
  351. data/vendor/depot_tools/python-bin/python3 +7 -0
  352. data/vendor/depot_tools/python_runner.sh +60 -0
  353. data/vendor/depot_tools/rdb +12 -0
  354. data/vendor/depot_tools/rdb.bat +7 -0
  355. data/vendor/depot_tools/recipes/OWNERS +4 -0
  356. data/vendor/depot_tools/recipes/README.recipes.md +1079 -0
  357. data/vendor/depot_tools/recipes/recipe_modules/OWNERS +1 -0
  358. data/vendor/depot_tools/recipes/recipe_modules/bot_update/OWNERS +2 -0
  359. data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +38 -0
  360. data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +516 -0
  361. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic.json +117 -0
  362. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_luci.json +117 -0
  363. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_with_branch_heads.json +118 -0
  364. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/clobber.json +211 -0
  365. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +194 -0
  366. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_rebase_patch_ref.json +211 -0
  367. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_reset.json +211 -0
  368. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/input_commit_with_id_without_repo.json +210 -0
  369. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/multiple_patch_refs.json +214 -0
  370. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_apply_patch_on_gclient.json +265 -0
  371. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_HEAD.json +65 -0
  372. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_a_branch_head.json +65 -0
  373. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_a_specific_commit.json +65 -0
  374. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_master.json +65 -0
  375. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/refs.json +212 -0
  376. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/reset_root_solution_revision.json +210 -0
  377. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/resolve_chromium_fixed_version.json +117 -0
  378. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +95 -0
  379. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +209 -0
  380. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +193 -0
  381. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle.json +265 -0
  382. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_branch_heads.json +261 -0
  383. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_feature_branch.json +261 -0
  384. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8_feature_branch.json +265 -0
  385. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_webrtc.json +265 -0
  386. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +265 -0
  387. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +265 -0
  388. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/unrecognized_commit_repo.json +8 -0
  389. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_tags.json +211 -0
  390. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.py +308 -0
  391. data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/__init__.py +0 -0
  392. data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +1258 -0
  393. data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +93 -0
  394. data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/do_not_retry_patch_failures_in_cq.py +42 -0
  395. data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/ensure_checkout.py +35 -0
  396. data/vendor/depot_tools/recipes/recipe_modules/cipd/__init__.py +9 -0
  397. data/vendor/depot_tools/recipes/recipe_modules/cipd/api.py +455 -0
  398. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic.json +403 -0
  399. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic_pkg.json +403 -0
  400. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-failed.json +82 -0
  401. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-many-instances.json +411 -0
  402. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/mac64.json +403 -0
  403. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_file.json +315 -0
  404. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_mode.json +313 -0
  405. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_verfile.json +313 -0
  406. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/win64.json +403 -0
  407. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.py +187 -0
  408. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk arch.json +5 -0
  409. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk bits.json +5 -0
  410. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_32.json +12 -0
  411. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_64.json +12 -0
  412. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_32.json +12 -0
  413. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_64.json +12 -0
  414. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_mips_64.json +12 -0
  415. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/mac_intel_64.json +12 -0
  416. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_32.json +12 -0
  417. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_64.json +12 -0
  418. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.py +59 -0
  419. data/vendor/depot_tools/recipes/recipe_modules/cipd/test_api.py +93 -0
  420. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/__init__.py +9 -0
  421. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/api.py +75 -0
  422. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic.json +83 -0
  423. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic_luci.json +83 -0
  424. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/win.json +83 -0
  425. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.py +55 -0
  426. data/vendor/depot_tools/recipes/recipe_modules/gclient/__init__.py +13 -0
  427. data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +428 -0
  428. data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +462 -0
  429. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/basic.json +238 -0
  430. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/revision.json +240 -0
  431. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/tryserver.json +238 -0
  432. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.py +95 -0
  433. data/vendor/depot_tools/recipes/recipe_modules/gclient/resources/diff_deps.py +16 -0
  434. data/vendor/depot_tools/recipes/recipe_modules/gclient/test_api.py +36 -0
  435. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/basic.json +55 -0
  436. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/dont have revision yet.json +84 -0
  437. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/no change, exception.json +83 -0
  438. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/windows.json +55 -0
  439. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.py +88 -0
  440. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/patch_project.py +92 -0
  441. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/sync_failure.py +24 -0
  442. data/vendor/depot_tools/recipes/recipe_modules/gerrit/__init__.py +8 -0
  443. data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +178 -0
  444. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +284 -0
  445. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.py +73 -0
  446. data/vendor/depot_tools/recipes/recipe_modules/gerrit/test_api.py +53 -0
  447. data/vendor/depot_tools/recipes/recipe_modules/git/__init__.py +11 -0
  448. data/vendor/depot_tools/recipes/recipe_modules/git/api.py +405 -0
  449. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic.json +217 -0
  450. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_branch.json +217 -0
  451. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_file_name.json +219 -0
  452. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_hash.json +216 -0
  453. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_ref.json +217 -0
  454. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_submodule_update_force.json +218 -0
  455. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_tags.json +218 -0
  456. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/can_fail_build.json +164 -0
  457. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cannot_fail_build.json +220 -0
  458. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cat-file_test.json +239 -0
  459. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_delta.json +290 -0
  460. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_failed.json +220 -0
  461. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output.json +222 -0
  462. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output_fails_build.json +111 -0
  463. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/curl_trace_file.json +218 -0
  464. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/git-cache-checkout.json +265 -0
  465. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/platform_win.json +217 -0
  466. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/rebase_failed.json +221 -0
  467. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/remote_not_origin.json +219 -0
  468. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/set_got_revision.json +218 -0
  469. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.py +170 -0
  470. data/vendor/depot_tools/recipes/recipe_modules/git/resources/git_setup.py +52 -0
  471. data/vendor/depot_tools/recipes/recipe_modules/git/test_api.py +18 -0
  472. data/vendor/depot_tools/recipes/recipe_modules/git_cl/__init__.py +5 -0
  473. data/vendor/depot_tools/recipes/recipe_modules/git_cl/api.py +50 -0
  474. data/vendor/depot_tools/recipes/recipe_modules/git_cl/config.py +22 -0
  475. data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.expected/basic.json +105 -0
  476. data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.py +47 -0
  477. data/vendor/depot_tools/recipes/recipe_modules/gitiles/OWNERS +2 -0
  478. data/vendor/depot_tools/recipes/recipe_modules/gitiles/__init__.py +12 -0
  479. data/vendor/depot_tools/recipes/recipe_modules/gitiles/api.py +257 -0
  480. data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.expected/basic.json +596 -0
  481. data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.py +93 -0
  482. data/vendor/depot_tools/recipes/recipe_modules/gitiles/resources/gerrit_client.py +251 -0
  483. data/vendor/depot_tools/recipes/recipe_modules/gitiles/test_api.py +95 -0
  484. data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.expected/basic.json +5 -0
  485. data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.py +49 -0
  486. data/vendor/depot_tools/recipes/recipe_modules/gsutil/__init__.py +4 -0
  487. data/vendor/depot_tools/recipes/recipe_modules/gsutil/api.py +222 -0
  488. data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.expected/basic.json +247 -0
  489. data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.py +92 -0
  490. data/vendor/depot_tools/recipes/recipe_modules/gsutil/resources/gsutil_smart_retry.py +69 -0
  491. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/__init__.py +36 -0
  492. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/api.py +140 -0
  493. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/ancient_version.json +83 -0
  494. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/automatic_version.json +83 -0
  495. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/explicit_version.json +83 -0
  496. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/linux.json +21 -0
  497. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/mac.json +83 -0
  498. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/win.json +21 -0
  499. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.py +42 -0
  500. data/vendor/depot_tools/recipes/recipe_modules/presubmit/__init__.py +27 -0
  501. data/vendor/depot_tools/recipes/recipe_modules/presubmit/api.py +251 -0
  502. data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.expected/basic.json +27 -0
  503. data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.py +19 -0
  504. data/vendor/depot_tools/recipes/recipe_modules/presubmit/properties.proto +14 -0
  505. data/vendor/depot_tools/recipes/recipe_modules/presubmit/test_api.py +19 -0
  506. data/vendor/depot_tools/recipes/recipe_modules/presubmit/tests/execute.py +247 -0
  507. data/vendor/depot_tools/recipes/recipe_modules/presubmit/tests/prepare.py +49 -0
  508. data/vendor/depot_tools/recipes/recipe_modules/tryserver/__init__.py +18 -0
  509. data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +264 -0
  510. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/basic_tags.json +57 -0
  511. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch.json +190 -0
  512. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch_and_target_ref.json +190 -0
  513. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch.json +21 -0
  514. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch_new.json +22 -0
  515. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.py +95 -0
  516. data/vendor/depot_tools/recipes/recipe_modules/tryserver/test_api.py +14 -0
  517. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_fetch_ref_timeout.py +29 -0
  518. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_owner.expected/basic.json +5 -0
  519. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_owner.py +22 -0
  520. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_target_ref.py +32 -0
  521. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/__init__.py +25 -0
  522. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/api.py +137 -0
  523. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json +21 -0
  524. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json +21 -0
  525. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json +108 -0
  526. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.py +21 -0
  527. data/vendor/depot_tools/recipes/recipes.py +249 -0
  528. data/vendor/depot_tools/recipes/recipes/fetch_end_to_end_test.expected/basic.json +175 -0
  529. data/vendor/depot_tools/recipes/recipes/fetch_end_to_end_test.py +56 -0
  530. data/vendor/depot_tools/recipes/trigger_recipe_roller.txt +13 -0
  531. data/vendor/depot_tools/repo +1194 -0
  532. data/vendor/depot_tools/roll-dep +21 -0
  533. data/vendor/depot_tools/roll-dep.bat +21 -0
  534. data/vendor/depot_tools/roll_dep.py +282 -0
  535. data/vendor/depot_tools/scm.py +415 -0
  536. data/vendor/depot_tools/setup_color.py +130 -0
  537. data/vendor/depot_tools/split_cl.py +263 -0
  538. data/vendor/depot_tools/subcommand.py +261 -0
  539. data/vendor/depot_tools/subprocess2.py +258 -0
  540. data/vendor/depot_tools/third_party/__init__.py +5 -0
  541. data/vendor/depot_tools/third_party/colorama/LICENSE.txt +27 -0
  542. data/vendor/depot_tools/third_party/colorama/README.chromium +12 -0
  543. data/vendor/depot_tools/third_party/colorama/README.rst +346 -0
  544. data/vendor/depot_tools/third_party/colorama/__init__.py +6 -0
  545. data/vendor/depot_tools/third_party/colorama/ansi.py +102 -0
  546. data/vendor/depot_tools/third_party/colorama/ansitowin32.py +257 -0
  547. data/vendor/depot_tools/third_party/colorama/initialise.py +80 -0
  548. data/vendor/depot_tools/third_party/colorama/win32.py +152 -0
  549. data/vendor/depot_tools/third_party/colorama/winterm.py +169 -0
  550. data/vendor/depot_tools/third_party/coverage/AUTHORS.txt +43 -0
  551. data/vendor/depot_tools/third_party/coverage/PKG-INFO +41 -0
  552. data/vendor/depot_tools/third_party/coverage/README.chromium +13 -0
  553. data/vendor/depot_tools/third_party/coverage/__init__.py +120 -0
  554. data/vendor/depot_tools/third_party/coverage/__main__.py +4 -0
  555. data/vendor/depot_tools/third_party/coverage/annotate.py +101 -0
  556. data/vendor/depot_tools/third_party/coverage/backward.py +184 -0
  557. data/vendor/depot_tools/third_party/coverage/bytecode.py +75 -0
  558. data/vendor/depot_tools/third_party/coverage/cmdline.py +740 -0
  559. data/vendor/depot_tools/third_party/coverage/codeunit.py +145 -0
  560. data/vendor/depot_tools/third_party/coverage/collector.py +353 -0
  561. data/vendor/depot_tools/third_party/coverage/config.py +213 -0
  562. data/vendor/depot_tools/third_party/coverage/control.py +776 -0
  563. data/vendor/depot_tools/third_party/coverage/data.py +278 -0
  564. data/vendor/depot_tools/third_party/coverage/debug.py +54 -0
  565. data/vendor/depot_tools/third_party/coverage/execfile.py +171 -0
  566. data/vendor/depot_tools/third_party/coverage/files.py +309 -0
  567. data/vendor/depot_tools/third_party/coverage/fullcoverage/encodings.py +57 -0
  568. data/vendor/depot_tools/third_party/coverage/html.py +387 -0
  569. data/vendor/depot_tools/third_party/coverage/htmlfiles/coverage_html.js +376 -0
  570. data/vendor/depot_tools/third_party/coverage/htmlfiles/index.html +104 -0
  571. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery-1.4.3.min.js +166 -0
  572. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.hotkeys.js +99 -0
  573. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.isonscreen.js +53 -0
  574. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.min.js +166 -0
  575. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.tablesorter.min.js +2 -0
  576. data/vendor/depot_tools/third_party/coverage/htmlfiles/keybd_closed.png +0 -0
  577. data/vendor/depot_tools/third_party/coverage/htmlfiles/keybd_open.png +0 -0
  578. data/vendor/depot_tools/third_party/coverage/htmlfiles/pyfile.html +90 -0
  579. data/vendor/depot_tools/third_party/coverage/htmlfiles/style.css +300 -0
  580. data/vendor/depot_tools/third_party/coverage/misc.py +163 -0
  581. data/vendor/depot_tools/third_party/coverage/parser.py +666 -0
  582. data/vendor/depot_tools/third_party/coverage/phystokens.py +208 -0
  583. data/vendor/depot_tools/third_party/coverage/report.py +92 -0
  584. data/vendor/depot_tools/third_party/coverage/results.py +286 -0
  585. data/vendor/depot_tools/third_party/coverage/summary.py +86 -0
  586. data/vendor/depot_tools/third_party/coverage/templite.py +166 -0
  587. data/vendor/depot_tools/third_party/coverage/version.py +9 -0
  588. data/vendor/depot_tools/third_party/coverage/xmlreport.py +155 -0
  589. data/vendor/depot_tools/third_party/httplib2/LICENSE +1339 -0
  590. data/vendor/depot_tools/third_party/httplib2/README.chromium +15 -0
  591. data/vendor/depot_tools/third_party/httplib2/__init__.py +1780 -0
  592. data/vendor/depot_tools/third_party/httplib2/cacerts.txt +2196 -0
  593. data/vendor/depot_tools/third_party/httplib2/iri2uri.py +110 -0
  594. data/vendor/depot_tools/third_party/httplib2/socks.py +448 -0
  595. data/vendor/depot_tools/third_party/repo/COPYING +202 -0
  596. data/vendor/depot_tools/third_party/repo/README.chromium +4 -0
  597. data/vendor/depot_tools/third_party/repo/__init__.py +0 -0
  598. data/vendor/depot_tools/third_party/repo/progress.py +117 -0
  599. data/vendor/depot_tools/third_party/retry_decorator/LICENSE.google +30 -0
  600. data/vendor/depot_tools/third_party/retry_decorator/__init__.py +0 -0
  601. data/vendor/depot_tools/third_party/retry_decorator/decorators.py +45 -0
  602. data/vendor/depot_tools/third_party/schema/.editorconfig +15 -0
  603. data/vendor/depot_tools/third_party/schema/.gitignore +174 -0
  604. data/vendor/depot_tools/third_party/schema/.travis.yml +37 -0
  605. data/vendor/depot_tools/third_party/schema/LICENSE-MIT +19 -0
  606. data/vendor/depot_tools/third_party/schema/MANIFEST.in +1 -0
  607. data/vendor/depot_tools/third_party/schema/README.chromium +12 -0
  608. data/vendor/depot_tools/third_party/schema/README.rst +382 -0
  609. data/vendor/depot_tools/third_party/schema/__init__.py +1 -0
  610. data/vendor/depot_tools/third_party/schema/schema.py +338 -0
  611. data/vendor/depot_tools/third_party/schema/setup.cfg +5 -0
  612. data/vendor/depot_tools/third_party/schema/setup.py +30 -0
  613. data/vendor/depot_tools/third_party/schema/test_schema.py +556 -0
  614. data/vendor/depot_tools/third_party/schema/tox.ini +33 -0
  615. data/vendor/depot_tools/third_party/six/LICENSE.txt +18 -0
  616. data/vendor/depot_tools/third_party/six/README.chromium +10 -0
  617. data/vendor/depot_tools/third_party/six/__init__.py +762 -0
  618. data/vendor/depot_tools/update_depot_tools +138 -0
  619. data/vendor/depot_tools/update_depot_tools.bat +65 -0
  620. data/vendor/depot_tools/update_depot_tools_toggle.py +38 -0
  621. data/vendor/depot_tools/upload_metrics.py +26 -0
  622. data/vendor/depot_tools/upload_to_google_storage.py +306 -0
  623. data/vendor/depot_tools/vpython +42 -0
  624. data/vendor/depot_tools/vpython.bat +7 -0
  625. data/vendor/depot_tools/vpython3 +55 -0
  626. data/vendor/depot_tools/vpython3.bat +12 -0
  627. data/vendor/depot_tools/watchlists.py +141 -0
  628. data/vendor/depot_tools/weekly +54 -0
  629. data/vendor/depot_tools/win32imports.py +61 -0
  630. data/vendor/depot_tools/win_toolchain/OWNERS +2 -0
  631. data/vendor/depot_tools/win_toolchain/README.md +74 -0
  632. data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +599 -0
  633. data/vendor/depot_tools/win_toolchain/package_from_installed.py +524 -0
  634. data/vendor/depot_tools/wtf +81 -0
  635. data/vendor/depot_tools/yapf +21 -0
  636. data/vendor/depot_tools/yapf.bat +12 -0
  637. data/vendor/depot_tools/zsh-goodies/README +6 -0
  638. data/vendor/depot_tools/zsh-goodies/_gclient +14 -0
  639. metadata +729 -0
@@ -0,0 +1,15 @@
1
+ Name: httplib2
2
+ Short Name: httplib2
3
+ URL: https://github.com/httplib2/httplib2
4
+ Version: 0.11.3
5
+ Revision: 70fb0c820d2e8211992b402d34444e4b32a1cb6e
6
+ License: MIT License
7
+
8
+ Description:
9
+ A comprehensive HTTP client library in Python.
10
+
11
+ Local Modifications:
12
+ Only python2 version is kept. Test and packaging code stripped.
13
+
14
+ Notes:
15
+ Required by oauth2client library.
@@ -0,0 +1,1780 @@
1
+ from __future__ import print_function
2
+ """
3
+ httplib2
4
+
5
+ A caching http interface that supports ETags and gzip
6
+ to conserve bandwidth.
7
+
8
+ Requires Python 2.3 or later
9
+
10
+ Changelog:
11
+ 2007-08-18, Rick: Modified so it's able to use a socks proxy if needed.
12
+
13
+ """
14
+
15
+ __author__ = "Joe Gregorio (joe@bitworking.org)"
16
+ __copyright__ = "Copyright 2006, Joe Gregorio"
17
+ __contributors__ = ["Thomas Broyer (t.broyer@ltgt.net)",
18
+ "James Antill",
19
+ "Xavier Verges Farrero",
20
+ "Jonathan Feinberg",
21
+ "Blair Zajac",
22
+ "Sam Ruby",
23
+ "Louis Nyffenegger",
24
+ "Alex Yu"]
25
+ __license__ = "MIT"
26
+ __version__ = '0.11.3'
27
+
28
+ import re
29
+ import sys
30
+ import email
31
+ import email.Utils
32
+ import email.Message
33
+ import email.FeedParser
34
+ import StringIO
35
+ import gzip
36
+ import zlib
37
+ import httplib
38
+ import urlparse
39
+ import urllib
40
+ import base64
41
+ import os
42
+ import copy
43
+ import calendar
44
+ import time
45
+ import random
46
+ import errno
47
+ try:
48
+ from hashlib import sha1 as _sha, md5 as _md5
49
+ except ImportError:
50
+ # prior to Python 2.5, these were separate modules
51
+ import sha
52
+ import md5
53
+ _sha = sha.new
54
+ _md5 = md5.new
55
+ import hmac
56
+ from gettext import gettext as _
57
+ import socket
58
+
59
+ try:
60
+ from httplib2 import socks
61
+ except ImportError:
62
+ try:
63
+ import socks
64
+ except (ImportError, AttributeError):
65
+ socks = None
66
+
67
+ # Build the appropriate socket wrapper for ssl
68
+ ssl = None
69
+ ssl_SSLError = None
70
+ ssl_CertificateError = None
71
+ try:
72
+ import ssl # python 2.6
73
+ except ImportError:
74
+ pass
75
+ if ssl is not None:
76
+ ssl_SSLError = getattr(ssl, 'SSLError', None)
77
+ ssl_CertificateError = getattr(ssl, 'CertificateError', None)
78
+
79
+
80
+ def _ssl_wrap_socket(sock, key_file, cert_file, disable_validation,
81
+ ca_certs, ssl_version, hostname):
82
+ if disable_validation:
83
+ cert_reqs = ssl.CERT_NONE
84
+ else:
85
+ cert_reqs = ssl.CERT_REQUIRED
86
+ if ssl_version is None:
87
+ ssl_version = ssl.PROTOCOL_SSLv23
88
+
89
+ if hasattr(ssl, 'SSLContext'): # Python 2.7.9
90
+ context = ssl.SSLContext(ssl_version)
91
+ context.verify_mode = cert_reqs
92
+ context.check_hostname = (cert_reqs != ssl.CERT_NONE)
93
+ if cert_file:
94
+ context.load_cert_chain(cert_file, key_file)
95
+ if ca_certs:
96
+ context.load_verify_locations(ca_certs)
97
+ return context.wrap_socket(sock, server_hostname=hostname)
98
+ else:
99
+ return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
100
+ cert_reqs=cert_reqs, ca_certs=ca_certs,
101
+ ssl_version=ssl_version)
102
+
103
+
104
+ def _ssl_wrap_socket_unsupported(sock, key_file, cert_file, disable_validation,
105
+ ca_certs, ssl_version, hostname):
106
+ if not disable_validation:
107
+ raise CertificateValidationUnsupported(
108
+ "SSL certificate validation is not supported without "
109
+ "the ssl module installed. To avoid this error, install "
110
+ "the ssl module, or explicity disable validation.")
111
+ ssl_sock = socket.ssl(sock, key_file, cert_file)
112
+ return httplib.FakeSocket(sock, ssl_sock)
113
+
114
+ if ssl is None:
115
+ _ssl_wrap_socket = _ssl_wrap_socket_unsupported
116
+
117
+
118
+ if sys.version_info >= (2,3):
119
+ from iri2uri import iri2uri
120
+ else:
121
+ def iri2uri(uri):
122
+ return uri
123
+
124
+ def has_timeout(timeout): # python 2.6
125
+ if hasattr(socket, '_GLOBAL_DEFAULT_TIMEOUT'):
126
+ return (timeout is not None and timeout is not socket._GLOBAL_DEFAULT_TIMEOUT)
127
+ return (timeout is not None)
128
+
129
+ __all__ = [
130
+ 'Http', 'Response', 'ProxyInfo', 'HttpLib2Error', 'RedirectMissingLocation',
131
+ 'RedirectLimit', 'FailedToDecompressContent',
132
+ 'UnimplementedDigestAuthOptionError',
133
+ 'UnimplementedHmacDigestAuthOptionError',
134
+ 'debuglevel', 'ProxiesUnavailableError']
135
+
136
+
137
+ # The httplib debug level, set to a non-zero value to get debug output
138
+ debuglevel = 0
139
+
140
+ # A request will be tried 'RETRIES' times if it fails at the socket/connection level.
141
+ RETRIES = 2
142
+
143
+ # Python 2.3 support
144
+ if sys.version_info < (2,4):
145
+ def sorted(seq):
146
+ seq.sort()
147
+ return seq
148
+
149
+
150
+ # Python 2.3 support
151
+ def HTTPResponse__getheaders(self):
152
+ """Return list of (header, value) tuples."""
153
+ if self.msg is None:
154
+ raise httplib.ResponseNotReady()
155
+ return self.msg.items()
156
+
157
+ if not hasattr(httplib.HTTPResponse, 'getheaders'):
158
+ httplib.HTTPResponse.getheaders = HTTPResponse__getheaders
159
+
160
+ # All exceptions raised here derive from HttpLib2Error
161
+ class HttpLib2Error(Exception): pass
162
+
163
+ # Some exceptions can be caught and optionally
164
+ # be turned back into responses.
165
+ class HttpLib2ErrorWithResponse(HttpLib2Error):
166
+ def __init__(self, desc, response, content):
167
+ self.response = response
168
+ self.content = content
169
+ HttpLib2Error.__init__(self, desc)
170
+
171
+ class RedirectMissingLocation(HttpLib2ErrorWithResponse): pass
172
+ class RedirectLimit(HttpLib2ErrorWithResponse): pass
173
+ class FailedToDecompressContent(HttpLib2ErrorWithResponse): pass
174
+ class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse): pass
175
+ class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse): pass
176
+
177
+ class MalformedHeader(HttpLib2Error): pass
178
+ class RelativeURIError(HttpLib2Error): pass
179
+ class ServerNotFoundError(HttpLib2Error): pass
180
+ class ProxiesUnavailableError(HttpLib2Error): pass
181
+ class CertificateValidationUnsupported(HttpLib2Error): pass
182
+ class SSLHandshakeError(HttpLib2Error): pass
183
+ class NotSupportedOnThisPlatform(HttpLib2Error): pass
184
+ class CertificateHostnameMismatch(SSLHandshakeError):
185
+ def __init__(self, desc, host, cert):
186
+ HttpLib2Error.__init__(self, desc)
187
+ self.host = host
188
+ self.cert = cert
189
+
190
+ class NotRunningAppEngineEnvironment(HttpLib2Error): pass
191
+
192
+ # Open Items:
193
+ # -----------
194
+ # Proxy support
195
+
196
+ # Are we removing the cached content too soon on PUT (only delete on 200 Maybe?)
197
+
198
+ # Pluggable cache storage (supports storing the cache in
199
+ # flat files by default. We need a plug-in architecture
200
+ # that can support Berkeley DB and Squid)
201
+
202
+ # == Known Issues ==
203
+ # Does not handle a resource that uses conneg and Last-Modified but no ETag as a cache validator.
204
+ # Does not handle Cache-Control: max-stale
205
+ # Does not use Age: headers when calculating cache freshness.
206
+
207
+
208
+ # The number of redirections to follow before giving up.
209
+ # Note that only GET redirects are automatically followed.
210
+ # Will also honor 301 requests by saving that info and never
211
+ # requesting that URI again.
212
+ DEFAULT_MAX_REDIRECTS = 5
213
+
214
+ try:
215
+ # Users can optionally provide a module that tells us where the CA_CERTS
216
+ # are located.
217
+ import ca_certs_locater
218
+ CA_CERTS = ca_certs_locater.get()
219
+ except ImportError:
220
+ # Default CA certificates file bundled with httplib2.
221
+ CA_CERTS = os.path.join(
222
+ os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt")
223
+
224
+ # Which headers are hop-by-hop headers by default
225
+ HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade']
226
+
227
+
228
+ def _get_end2end_headers(response):
229
+ hopbyhop = list(HOP_BY_HOP)
230
+ hopbyhop.extend([x.strip() for x in response.get('connection', '').split(',')])
231
+ return [header for header in response.keys() if header not in hopbyhop]
232
+
233
+ URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?")
234
+
235
+
236
+ def parse_uri(uri):
237
+ """Parses a URI using the regex given in Appendix B of RFC 3986.
238
+
239
+ (scheme, authority, path, query, fragment) = parse_uri(uri)
240
+ """
241
+ groups = URI.match(uri).groups()
242
+ return (groups[1], groups[3], groups[4], groups[6], groups[8])
243
+
244
+
245
+ def urlnorm(uri):
246
+ (scheme, authority, path, query, fragment) = parse_uri(uri)
247
+ if not scheme or not authority:
248
+ raise RelativeURIError("Only absolute URIs are allowed. uri = %s" % uri)
249
+ authority = authority.lower()
250
+ scheme = scheme.lower()
251
+ if not path:
252
+ path = "/"
253
+ # Could do syntax based normalization of the URI before
254
+ # computing the digest. See Section 6.2.2 of Std 66.
255
+ request_uri = query and "?".join([path, query]) or path
256
+ scheme = scheme.lower()
257
+ defrag_uri = scheme + "://" + authority + request_uri
258
+ return scheme, authority, request_uri, defrag_uri
259
+
260
+
261
+ # Cache filename construction (original borrowed from Venus http://intertwingly.net/code/venus/)
262
+ re_url_scheme = re.compile(r'^\w+://')
263
+ re_slash = re.compile(r'[?/:|]+')
264
+
265
+
266
+ def safename(filename):
267
+ """Return a filename suitable for the cache.
268
+
269
+ Strips dangerous and common characters to create a filename we
270
+ can use to store the cache in.
271
+ """
272
+
273
+ try:
274
+ if re_url_scheme.match(filename):
275
+ if isinstance(filename,str):
276
+ filename = filename.decode('utf-8')
277
+ filename = filename.encode('idna')
278
+ else:
279
+ filename = filename.encode('idna')
280
+ except UnicodeError:
281
+ pass
282
+ if isinstance(filename,unicode):
283
+ filename=filename.encode('utf-8')
284
+ filemd5 = _md5(filename).hexdigest()
285
+ filename = re_url_scheme.sub("", filename)
286
+ filename = re_slash.sub(",", filename)
287
+
288
+ # limit length of filename
289
+ if len(filename)>200:
290
+ filename=filename[:200]
291
+ return ",".join((filename, filemd5))
292
+
293
+ NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+')
294
+
295
+
296
+ def _normalize_headers(headers):
297
+ return dict([ (key.lower(), NORMALIZE_SPACE.sub(value, ' ').strip()) for (key, value) in headers.iteritems()])
298
+
299
+
300
+ def _parse_cache_control(headers):
301
+ retval = {}
302
+ if 'cache-control' in headers:
303
+ parts = headers['cache-control'].split(',')
304
+ parts_with_args = [tuple([x.strip().lower() for x in part.split("=", 1)]) for part in parts if -1 != part.find("=")]
305
+ parts_wo_args = [(name.strip().lower(), 1) for name in parts if -1 == name.find("=")]
306
+ retval = dict(parts_with_args + parts_wo_args)
307
+ return retval
308
+
309
+ # Whether to use a strict mode to parse WWW-Authenticate headers
310
+ # Might lead to bad results in case of ill-formed header value,
311
+ # so disabled by default, falling back to relaxed parsing.
312
+ # Set to true to turn on, usefull for testing servers.
313
+ USE_WWW_AUTH_STRICT_PARSING = 0
314
+
315
+ # In regex below:
316
+ # [^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+ matches a "token" as defined by HTTP
317
+ # "(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?" matches a "quoted-string" as defined by HTTP, when LWS have already been replaced by a single space
318
+ # Actually, as an auth-param value can be either a token or a quoted-string, they are combined in a single pattern which matches both:
319
+ # \"?((?<=\")(?:[^\0-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x08\x0A-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"?
320
+ WWW_AUTH_STRICT = re.compile(r"^(?:\s*(?:,\s*)?([^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+)\s*=\s*\"?((?<=\")(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"?)(.*)$")
321
+ WWW_AUTH_RELAXED = re.compile(r"^(?:\s*(?:,\s*)?([^ \t\r\n=]+)\s*=\s*\"?((?<=\")(?:[^\\\"]|\\.)*?(?=\")|(?<!\")[^ \t\r\n,]+(?!\"))\"?)(.*)$")
322
+ UNQUOTE_PAIRS = re.compile(r'\\(.)')
323
+ def _parse_www_authenticate(headers, headername='www-authenticate'):
324
+ """Returns a dictionary of dictionaries, one dict
325
+ per auth_scheme."""
326
+ retval = {}
327
+ if headername in headers:
328
+ try:
329
+
330
+ authenticate = headers[headername].strip()
331
+ www_auth = USE_WWW_AUTH_STRICT_PARSING and WWW_AUTH_STRICT or WWW_AUTH_RELAXED
332
+ while authenticate:
333
+ # Break off the scheme at the beginning of the line
334
+ if headername == 'authentication-info':
335
+ (auth_scheme, the_rest) = ('digest', authenticate)
336
+ else:
337
+ (auth_scheme, the_rest) = authenticate.split(" ", 1)
338
+ # Now loop over all the key value pairs that come after the scheme,
339
+ # being careful not to roll into the next scheme
340
+ match = www_auth.search(the_rest)
341
+ auth_params = {}
342
+ while match:
343
+ if match and len(match.groups()) == 3:
344
+ (key, value, the_rest) = match.groups()
345
+ auth_params[key.lower()] = UNQUOTE_PAIRS.sub(r'\1', value) # '\\'.join([x.replace('\\', '') for x in value.split('\\\\')])
346
+ match = www_auth.search(the_rest)
347
+ retval[auth_scheme.lower()] = auth_params
348
+ authenticate = the_rest.strip()
349
+
350
+ except ValueError:
351
+ raise MalformedHeader("WWW-Authenticate")
352
+ return retval
353
+
354
+
355
+ # TODO: add current time as _entry_disposition argument to avoid sleep in tests
356
+ def _entry_disposition(response_headers, request_headers):
357
+ """Determine freshness from the Date, Expires and Cache-Control headers.
358
+
359
+ We don't handle the following:
360
+
361
+ 1. Cache-Control: max-stale
362
+ 2. Age: headers are not used in the calculations.
363
+
364
+ Not that this algorithm is simpler than you might think
365
+ because we are operating as a private (non-shared) cache.
366
+ This lets us ignore 's-maxage'. We can also ignore
367
+ 'proxy-invalidate' since we aren't a proxy.
368
+ We will never return a stale document as
369
+ fresh as a design decision, and thus the non-implementation
370
+ of 'max-stale'. This also lets us safely ignore 'must-revalidate'
371
+ since we operate as if every server has sent 'must-revalidate'.
372
+ Since we are private we get to ignore both 'public' and
373
+ 'private' parameters. We also ignore 'no-transform' since
374
+ we don't do any transformations.
375
+ The 'no-store' parameter is handled at a higher level.
376
+ So the only Cache-Control parameters we look at are:
377
+
378
+ no-cache
379
+ only-if-cached
380
+ max-age
381
+ min-fresh
382
+ """
383
+
384
+ retval = "STALE"
385
+ cc = _parse_cache_control(request_headers)
386
+ cc_response = _parse_cache_control(response_headers)
387
+
388
+ if 'pragma' in request_headers and request_headers['pragma'].lower().find('no-cache') != -1:
389
+ retval = "TRANSPARENT"
390
+ if 'cache-control' not in request_headers:
391
+ request_headers['cache-control'] = 'no-cache'
392
+ elif 'no-cache' in cc:
393
+ retval = "TRANSPARENT"
394
+ elif 'no-cache' in cc_response:
395
+ retval = "STALE"
396
+ elif 'only-if-cached' in cc:
397
+ retval = "FRESH"
398
+ elif 'date' in response_headers:
399
+ date = calendar.timegm(email.Utils.parsedate_tz(response_headers['date']))
400
+ now = time.time()
401
+ current_age = max(0, now - date)
402
+ if 'max-age' in cc_response:
403
+ try:
404
+ freshness_lifetime = int(cc_response['max-age'])
405
+ except ValueError:
406
+ freshness_lifetime = 0
407
+ elif 'expires' in response_headers:
408
+ expires = email.Utils.parsedate_tz(response_headers['expires'])
409
+ if None == expires:
410
+ freshness_lifetime = 0
411
+ else:
412
+ freshness_lifetime = max(0, calendar.timegm(expires) - date)
413
+ else:
414
+ freshness_lifetime = 0
415
+ if 'max-age' in cc:
416
+ try:
417
+ freshness_lifetime = int(cc['max-age'])
418
+ except ValueError:
419
+ freshness_lifetime = 0
420
+ if 'min-fresh' in cc:
421
+ try:
422
+ min_fresh = int(cc['min-fresh'])
423
+ except ValueError:
424
+ min_fresh = 0
425
+ current_age += min_fresh
426
+ if freshness_lifetime > current_age:
427
+ retval = "FRESH"
428
+ return retval
429
+
430
+
431
+ def _decompressContent(response, new_content):
432
+ content = new_content
433
+ try:
434
+ encoding = response.get('content-encoding', None)
435
+ if encoding in ['gzip', 'deflate']:
436
+ if encoding == 'gzip':
437
+ content = gzip.GzipFile(fileobj=StringIO.StringIO(new_content)).read()
438
+ if encoding == 'deflate':
439
+ content = zlib.decompress(content, -zlib.MAX_WBITS)
440
+ response['content-length'] = str(len(content))
441
+ # Record the historical presence of the encoding in a way the won't interfere.
442
+ response['-content-encoding'] = response['content-encoding']
443
+ del response['content-encoding']
444
+ except (IOError, zlib.error):
445
+ content = ""
446
+ raise FailedToDecompressContent(_("Content purported to be compressed with %s but failed to decompress.") % response.get('content-encoding'), response, content)
447
+ return content
448
+
449
+
450
+ def _updateCache(request_headers, response_headers, content, cache, cachekey):
451
+ if cachekey:
452
+ cc = _parse_cache_control(request_headers)
453
+ cc_response = _parse_cache_control(response_headers)
454
+ if 'no-store' in cc or 'no-store' in cc_response:
455
+ cache.delete(cachekey)
456
+ else:
457
+ info = email.Message.Message()
458
+ for key, value in response_headers.iteritems():
459
+ if key not in ['status','content-encoding','transfer-encoding']:
460
+ info[key] = value
461
+
462
+ # Add annotations to the cache to indicate what headers
463
+ # are variant for this request.
464
+ vary = response_headers.get('vary', None)
465
+ if vary:
466
+ vary_headers = vary.lower().replace(' ', '').split(',')
467
+ for header in vary_headers:
468
+ key = '-varied-%s' % header
469
+ try:
470
+ info[key] = request_headers[header]
471
+ except KeyError:
472
+ pass
473
+
474
+ status = response_headers.status
475
+ if status == 304:
476
+ status = 200
477
+
478
+ status_header = 'status: %d\r\n' % status
479
+
480
+ header_str = info.as_string()
481
+
482
+ header_str = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", header_str)
483
+ text = "".join([status_header, header_str, content])
484
+
485
+ cache.set(cachekey, text)
486
+
487
+ def _cnonce():
488
+ dig = _md5("%s:%s" % (time.ctime(), ["0123456789"[random.randrange(0, 9)] for i in range(20)])).hexdigest()
489
+ return dig[:16]
490
+
491
+ def _wsse_username_token(cnonce, iso_now, password):
492
+ return base64.b64encode(_sha("%s%s%s" % (cnonce, iso_now, password)).digest()).strip()
493
+
494
+
495
+ # For credentials we need two things, first
496
+ # a pool of credential to try (not necesarily tied to BAsic, Digest, etc.)
497
+ # Then we also need a list of URIs that have already demanded authentication
498
+ # That list is tricky since sub-URIs can take the same auth, or the
499
+ # auth scheme may change as you descend the tree.
500
+ # So we also need each Auth instance to be able to tell us
501
+ # how close to the 'top' it is.
502
+
503
+ class Authentication(object):
504
+ def __init__(self, credentials, host, request_uri, headers, response, content, http):
505
+ (scheme, authority, path, query, fragment) = parse_uri(request_uri)
506
+ self.path = path
507
+ self.host = host
508
+ self.credentials = credentials
509
+ self.http = http
510
+
511
+ def depth(self, request_uri):
512
+ (scheme, authority, path, query, fragment) = parse_uri(request_uri)
513
+ return request_uri[len(self.path):].count("/")
514
+
515
+ def inscope(self, host, request_uri):
516
+ # XXX Should we normalize the request_uri?
517
+ (scheme, authority, path, query, fragment) = parse_uri(request_uri)
518
+ return (host == self.host) and path.startswith(self.path)
519
+
520
+ def request(self, method, request_uri, headers, content):
521
+ """Modify the request headers to add the appropriate
522
+ Authorization header. Over-ride this in sub-classes."""
523
+ pass
524
+
525
+ def response(self, response, content):
526
+ """Gives us a chance to update with new nonces
527
+ or such returned from the last authorized response.
528
+ Over-rise this in sub-classes if necessary.
529
+
530
+ Return TRUE is the request is to be retried, for
531
+ example Digest may return stale=true.
532
+ """
533
+ return False
534
+
535
+
536
+ class BasicAuthentication(Authentication):
537
+ def __init__(self, credentials, host, request_uri, headers, response, content, http):
538
+ Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http)
539
+
540
+ def request(self, method, request_uri, headers, content):
541
+ """Modify the request headers to add the appropriate
542
+ Authorization header."""
543
+ headers['authorization'] = 'Basic ' + base64.b64encode("%s:%s" % self.credentials).strip()
544
+
545
+
546
+ class DigestAuthentication(Authentication):
547
+ """Only do qop='auth' and MD5, since that
548
+ is all Apache currently implements"""
549
+ def __init__(self, credentials, host, request_uri, headers, response, content, http):
550
+ Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http)
551
+ challenge = _parse_www_authenticate(response, 'www-authenticate')
552
+ self.challenge = challenge['digest']
553
+ qop = self.challenge.get('qop', 'auth')
554
+ self.challenge['qop'] = ('auth' in [x.strip() for x in qop.split()]) and 'auth' or None
555
+ if self.challenge['qop'] is None:
556
+ raise UnimplementedDigestAuthOptionError( _("Unsupported value for qop: %s." % qop))
557
+ self.challenge['algorithm'] = self.challenge.get('algorithm', 'MD5').upper()
558
+ if self.challenge['algorithm'] != 'MD5':
559
+ raise UnimplementedDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm']))
560
+ self.A1 = "".join([self.credentials[0], ":", self.challenge['realm'], ":", self.credentials[1]])
561
+ self.challenge['nc'] = 1
562
+
563
+ def request(self, method, request_uri, headers, content, cnonce = None):
564
+ """Modify the request headers"""
565
+ H = lambda x: _md5(x).hexdigest()
566
+ KD = lambda s, d: H("%s:%s" % (s, d))
567
+ A2 = "".join([method, ":", request_uri])
568
+ self.challenge['cnonce'] = cnonce or _cnonce()
569
+ request_digest = '"%s"' % KD(H(self.A1), "%s:%s:%s:%s:%s" % (
570
+ self.challenge['nonce'],
571
+ '%08x' % self.challenge['nc'],
572
+ self.challenge['cnonce'],
573
+ self.challenge['qop'], H(A2)))
574
+ headers['authorization'] = 'Digest username="%s", realm="%s", nonce="%s", uri="%s", algorithm=%s, response=%s, qop=%s, nc=%08x, cnonce="%s"' % (
575
+ self.credentials[0],
576
+ self.challenge['realm'],
577
+ self.challenge['nonce'],
578
+ request_uri,
579
+ self.challenge['algorithm'],
580
+ request_digest,
581
+ self.challenge['qop'],
582
+ self.challenge['nc'],
583
+ self.challenge['cnonce'])
584
+ if self.challenge.get('opaque'):
585
+ headers['authorization'] += ', opaque="%s"' % self.challenge['opaque']
586
+ self.challenge['nc'] += 1
587
+
588
+ def response(self, response, content):
589
+ if 'authentication-info' not in response:
590
+ challenge = _parse_www_authenticate(response, 'www-authenticate').get('digest', {})
591
+ if 'true' == challenge.get('stale'):
592
+ self.challenge['nonce'] = challenge['nonce']
593
+ self.challenge['nc'] = 1
594
+ return True
595
+ else:
596
+ updated_challenge = _parse_www_authenticate(response, 'authentication-info').get('digest', {})
597
+
598
+ if 'nextnonce' in updated_challenge:
599
+ self.challenge['nonce'] = updated_challenge['nextnonce']
600
+ self.challenge['nc'] = 1
601
+ return False
602
+
603
+
604
+ class HmacDigestAuthentication(Authentication):
605
+ """Adapted from Robert Sayre's code and DigestAuthentication above."""
606
+ __author__ = "Thomas Broyer (t.broyer@ltgt.net)"
607
+
608
+ def __init__(self, credentials, host, request_uri, headers, response, content, http):
609
+ Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http)
610
+ challenge = _parse_www_authenticate(response, 'www-authenticate')
611
+ self.challenge = challenge['hmacdigest']
612
+ # TODO: self.challenge['domain']
613
+ self.challenge['reason'] = self.challenge.get('reason', 'unauthorized')
614
+ if self.challenge['reason'] not in ['unauthorized', 'integrity']:
615
+ self.challenge['reason'] = 'unauthorized'
616
+ self.challenge['salt'] = self.challenge.get('salt', '')
617
+ if not self.challenge.get('snonce'):
618
+ raise UnimplementedHmacDigestAuthOptionError( _("The challenge doesn't contain a server nonce, or this one is empty."))
619
+ self.challenge['algorithm'] = self.challenge.get('algorithm', 'HMAC-SHA-1')
620
+ if self.challenge['algorithm'] not in ['HMAC-SHA-1', 'HMAC-MD5']:
621
+ raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm']))
622
+ self.challenge['pw-algorithm'] = self.challenge.get('pw-algorithm', 'SHA-1')
623
+ if self.challenge['pw-algorithm'] not in ['SHA-1', 'MD5']:
624
+ raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for pw-algorithm: %s." % self.challenge['pw-algorithm']))
625
+ if self.challenge['algorithm'] == 'HMAC-MD5':
626
+ self.hashmod = _md5
627
+ else:
628
+ self.hashmod = _sha
629
+ if self.challenge['pw-algorithm'] == 'MD5':
630
+ self.pwhashmod = _md5
631
+ else:
632
+ self.pwhashmod = _sha
633
+ self.key = "".join([self.credentials[0], ":",
634
+ self.pwhashmod.new("".join([self.credentials[1], self.challenge['salt']])).hexdigest().lower(),
635
+ ":", self.challenge['realm']])
636
+ self.key = self.pwhashmod.new(self.key).hexdigest().lower()
637
+
638
+ def request(self, method, request_uri, headers, content):
639
+ """Modify the request headers"""
640
+ keys = _get_end2end_headers(headers)
641
+ keylist = "".join(["%s " % k for k in keys])
642
+ headers_val = "".join([headers[k] for k in keys])
643
+ created = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime())
644
+ cnonce = _cnonce()
645
+ request_digest = "%s:%s:%s:%s:%s" % (method, request_uri, cnonce, self.challenge['snonce'], headers_val)
646
+ request_digest = hmac.new(self.key, request_digest, self.hashmod).hexdigest().lower()
647
+ headers['authorization'] = 'HMACDigest username="%s", realm="%s", snonce="%s", cnonce="%s", uri="%s", created="%s", response="%s", headers="%s"' % (
648
+ self.credentials[0],
649
+ self.challenge['realm'],
650
+ self.challenge['snonce'],
651
+ cnonce,
652
+ request_uri,
653
+ created,
654
+ request_digest,
655
+ keylist)
656
+
657
+ def response(self, response, content):
658
+ challenge = _parse_www_authenticate(response, 'www-authenticate').get('hmacdigest', {})
659
+ if challenge.get('reason') in ['integrity', 'stale']:
660
+ return True
661
+ return False
662
+
663
+
664
+ class WsseAuthentication(Authentication):
665
+ """This is thinly tested and should not be relied upon.
666
+ At this time there isn't any third party server to test against.
667
+ Blogger and TypePad implemented this algorithm at one point
668
+ but Blogger has since switched to Basic over HTTPS and
669
+ TypePad has implemented it wrong, by never issuing a 401
670
+ challenge but instead requiring your client to telepathically know that
671
+ their endpoint is expecting WSSE profile="UsernameToken"."""
672
+ def __init__(self, credentials, host, request_uri, headers, response, content, http):
673
+ Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http)
674
+
675
+ def request(self, method, request_uri, headers, content):
676
+ """Modify the request headers to add the appropriate
677
+ Authorization header."""
678
+ headers['authorization'] = 'WSSE profile="UsernameToken"'
679
+ iso_now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
680
+ cnonce = _cnonce()
681
+ password_digest = _wsse_username_token(cnonce, iso_now, self.credentials[1])
682
+ headers['X-WSSE'] = 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % (
683
+ self.credentials[0],
684
+ password_digest,
685
+ cnonce,
686
+ iso_now)
687
+
688
+
689
+ class GoogleLoginAuthentication(Authentication):
690
+ def __init__(self, credentials, host, request_uri, headers, response, content, http):
691
+ from urllib import urlencode
692
+ Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http)
693
+ challenge = _parse_www_authenticate(response, 'www-authenticate')
694
+ service = challenge['googlelogin'].get('service', 'xapi')
695
+ # Bloggger actually returns the service in the challenge
696
+ # For the rest we guess based on the URI
697
+ if service == 'xapi' and request_uri.find("calendar") > 0:
698
+ service = "cl"
699
+ # No point in guessing Base or Spreadsheet
700
+ #elif request_uri.find("spreadsheets") > 0:
701
+ # service = "wise"
702
+
703
+ auth = dict(Email=credentials[0], Passwd=credentials[1], service=service, source=headers['user-agent'])
704
+ resp, content = self.http.request("https://www.google.com/accounts/ClientLogin", method="POST", body=urlencode(auth), headers={'Content-Type': 'application/x-www-form-urlencoded'})
705
+ lines = content.split('\n')
706
+ d = dict([tuple(line.split("=", 1)) for line in lines if line])
707
+ if resp.status == 403:
708
+ self.Auth = ""
709
+ else:
710
+ self.Auth = d['Auth']
711
+
712
+ def request(self, method, request_uri, headers, content):
713
+ """Modify the request headers to add the appropriate
714
+ Authorization header."""
715
+ headers['authorization'] = 'GoogleLogin Auth=' + self.Auth
716
+
717
+
718
+ AUTH_SCHEME_CLASSES = {
719
+ "basic": BasicAuthentication,
720
+ "wsse": WsseAuthentication,
721
+ "digest": DigestAuthentication,
722
+ "hmacdigest": HmacDigestAuthentication,
723
+ "googlelogin": GoogleLoginAuthentication
724
+ }
725
+
726
+ AUTH_SCHEME_ORDER = ["hmacdigest", "googlelogin", "digest", "wsse", "basic"]
727
+
728
+
729
+ class FileCache(object):
730
+ """Uses a local directory as a store for cached files.
731
+ Not really safe to use if multiple threads or processes are going to
732
+ be running on the same cache.
733
+ """
734
+ def __init__(self, cache, safe=safename): # use safe=lambda x: md5.new(x).hexdigest() for the old behavior
735
+ self.cache = cache
736
+ self.safe = safe
737
+ if not os.path.exists(cache):
738
+ os.makedirs(self.cache)
739
+
740
+ def get(self, key):
741
+ retval = None
742
+ cacheFullPath = os.path.join(self.cache, self.safe(key))
743
+ try:
744
+ f = file(cacheFullPath, "rb")
745
+ retval = f.read()
746
+ f.close()
747
+ except IOError:
748
+ pass
749
+ return retval
750
+
751
+ def set(self, key, value):
752
+ cacheFullPath = os.path.join(self.cache, self.safe(key))
753
+ f = file(cacheFullPath, "wb")
754
+ f.write(value)
755
+ f.close()
756
+
757
+ def delete(self, key):
758
+ cacheFullPath = os.path.join(self.cache, self.safe(key))
759
+ if os.path.exists(cacheFullPath):
760
+ os.remove(cacheFullPath)
761
+
762
+
763
+ class Credentials(object):
764
+ def __init__(self):
765
+ self.credentials = []
766
+
767
+ def add(self, name, password, domain=""):
768
+ self.credentials.append((domain.lower(), name, password))
769
+
770
+ def clear(self):
771
+ self.credentials = []
772
+
773
+ def iter(self, domain):
774
+ for (cdomain, name, password) in self.credentials:
775
+ if cdomain == "" or domain == cdomain:
776
+ yield (name, password)
777
+
778
+
779
+ class KeyCerts(Credentials):
780
+ """Identical to Credentials except that
781
+ name/password are mapped to key/cert."""
782
+ pass
783
+
784
+
785
+ class AllHosts(object):
786
+ pass
787
+
788
+
789
+ class ProxyInfo(object):
790
+ """Collect information required to use a proxy."""
791
+ bypass_hosts = ()
792
+
793
+ def __init__(self, proxy_type, proxy_host, proxy_port,
794
+ proxy_rdns=True, proxy_user=None, proxy_pass=None, proxy_headers=None):
795
+ """
796
+ Args:
797
+ proxy_type: The type of proxy server. This must be set to one of
798
+ socks.PROXY_TYPE_XXX constants. For example:
799
+
800
+ p = ProxyInfo(proxy_type=socks.PROXY_TYPE_HTTP,
801
+ proxy_host='localhost', proxy_port=8000)
802
+
803
+ proxy_host: The hostname or IP address of the proxy server.
804
+
805
+ proxy_port: The port that the proxy server is running on.
806
+
807
+ proxy_rdns: If True (default), DNS queries will not be performed
808
+ locally, and instead, handed to the proxy to resolve. This is useful
809
+ if the network does not allow resolution of non-local names. In
810
+ httplib2 0.9 and earlier, this defaulted to False.
811
+
812
+ proxy_user: The username used to authenticate with the proxy server.
813
+
814
+ proxy_pass: The password used to authenticate with the proxy server.
815
+
816
+ proxy_headers: Additional or modified headers for the proxy connect request.
817
+ """
818
+ self.proxy_type = proxy_type
819
+ self.proxy_host = proxy_host
820
+ self.proxy_port = proxy_port
821
+ self.proxy_rdns = proxy_rdns
822
+ self.proxy_user = proxy_user
823
+ self.proxy_pass = proxy_pass
824
+ self.proxy_headers = proxy_headers
825
+
826
+ def astuple(self):
827
+ return (self.proxy_type, self.proxy_host, self.proxy_port,
828
+ self.proxy_rdns, self.proxy_user, self.proxy_pass, self.proxy_headers)
829
+
830
+ def isgood(self):
831
+ return (self.proxy_host != None) and (self.proxy_port != None)
832
+
833
+ def applies_to(self, hostname):
834
+ return not self.bypass_host(hostname)
835
+
836
+ def bypass_host(self, hostname):
837
+ """Has this host been excluded from the proxy config"""
838
+ if self.bypass_hosts is AllHosts:
839
+ return True
840
+
841
+ hostname = '.' + hostname.lstrip('.')
842
+ for skip_name in self.bypass_hosts:
843
+ # *.suffix
844
+ if skip_name.startswith('.') and hostname.endswith(skip_name):
845
+ return True
846
+ # exact match
847
+ if hostname == '.' + skip_name:
848
+ return True
849
+ return False
850
+
851
+ def __repr__(self):
852
+ return (
853
+ '<ProxyInfo type={p.proxy_type} host:port={p.proxy_host}:{p.proxy_port} rdns={p.proxy_rdns}' +
854
+ ' user={p.proxy_user} headers={p.proxy_headers}>').format(p=self)
855
+
856
+
857
+ def proxy_info_from_environment(method='http'):
858
+ """
859
+ Read proxy info from the environment variables.
860
+ """
861
+ if method not in ['http', 'https']:
862
+ return
863
+
864
+ env_var = method + '_proxy'
865
+ url = os.environ.get(env_var, os.environ.get(env_var.upper()))
866
+ if not url:
867
+ return
868
+ return proxy_info_from_url(url, method, None)
869
+
870
+
871
+ def proxy_info_from_url(url, method='http', noproxy=None):
872
+ """
873
+ Construct a ProxyInfo from a URL (such as http_proxy env var)
874
+ """
875
+ url = urlparse.urlparse(url)
876
+ username = None
877
+ password = None
878
+ port = None
879
+ if '@' in url[1]:
880
+ ident, host_port = url[1].split('@', 1)
881
+ if ':' in ident:
882
+ username, password = ident.split(':', 1)
883
+ else:
884
+ password = ident
885
+ else:
886
+ host_port = url[1]
887
+ if ':' in host_port:
888
+ host, port = host_port.split(':', 1)
889
+ else:
890
+ host = host_port
891
+
892
+ if port:
893
+ port = int(port)
894
+ else:
895
+ port = dict(https=443, http=80)[method]
896
+
897
+ proxy_type = 3 # socks.PROXY_TYPE_HTTP
898
+ pi = ProxyInfo(
899
+ proxy_type = proxy_type,
900
+ proxy_host = host,
901
+ proxy_port = port,
902
+ proxy_user = username or None,
903
+ proxy_pass = password or None,
904
+ proxy_headers = None,
905
+ )
906
+
907
+ bypass_hosts = []
908
+ # If not given an explicit noproxy value, respect values in env vars.
909
+ if noproxy is None:
910
+ noproxy = os.environ.get('no_proxy', os.environ.get('NO_PROXY', ''))
911
+ # Special case: A single '*' character means all hosts should be bypassed.
912
+ if noproxy == '*':
913
+ bypass_hosts = AllHosts
914
+ elif noproxy.strip():
915
+ bypass_hosts = noproxy.split(',')
916
+ bypass_hosts = filter(bool, bypass_hosts) # To exclude empty string.
917
+
918
+ pi.bypass_hosts = bypass_hosts
919
+ return pi
920
+
921
+
922
+ class HTTPConnectionWithTimeout(httplib.HTTPConnection):
923
+ """
924
+ HTTPConnection subclass that supports timeouts
925
+
926
+ All timeouts are in seconds. If None is passed for timeout then
927
+ Python's default timeout for sockets will be used. See for example
928
+ the docs of socket.setdefaulttimeout():
929
+ http://docs.python.org/library/socket.html#socket.setdefaulttimeout
930
+ """
931
+
932
+ def __init__(self, host, port=None, strict=None, timeout=None, proxy_info=None):
933
+ httplib.HTTPConnection.__init__(self, host, port, strict)
934
+ self.timeout = timeout
935
+ self.proxy_info = proxy_info
936
+
937
+ def connect(self):
938
+ """Connect to the host and port specified in __init__."""
939
+ # Mostly verbatim from httplib.py.
940
+ if self.proxy_info and socks is None:
941
+ raise ProxiesUnavailableError(
942
+ 'Proxy support missing but proxy use was requested!')
943
+ msg = "getaddrinfo returns an empty list"
944
+ if self.proxy_info and self.proxy_info.isgood():
945
+ use_proxy = True
946
+ proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers = self.proxy_info.astuple()
947
+
948
+ host = proxy_host
949
+ port = proxy_port
950
+ else:
951
+ use_proxy = False
952
+
953
+ host = self.host
954
+ port = self.port
955
+
956
+ for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
957
+ af, socktype, proto, canonname, sa = res
958
+ try:
959
+ if use_proxy:
960
+ self.sock = socks.socksocket(af, socktype, proto)
961
+ self.sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)
962
+ else:
963
+ self.sock = socket.socket(af, socktype, proto)
964
+ self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
965
+ # Different from httplib: support timeouts.
966
+ if has_timeout(self.timeout):
967
+ self.sock.settimeout(self.timeout)
968
+ # End of difference from httplib.
969
+ if self.debuglevel > 0:
970
+ print("connect: (%s, %s) ************" % (self.host, self.port))
971
+ if use_proxy:
972
+ print("proxy: %s ************" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)))
973
+ if use_proxy:
974
+ self.sock.connect((self.host, self.port) + sa[2:])
975
+ else:
976
+ self.sock.connect(sa)
977
+ except socket.error as msg:
978
+ if self.debuglevel > 0:
979
+ print("connect fail: (%s, %s)" % (self.host, self.port))
980
+ if use_proxy:
981
+ print("proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)))
982
+ if self.sock:
983
+ self.sock.close()
984
+ self.sock = None
985
+ continue
986
+ break
987
+ if not self.sock:
988
+ raise socket.error, msg
989
+
990
+
991
+ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
992
+ """
993
+ This class allows communication via SSL.
994
+
995
+ All timeouts are in seconds. If None is passed for timeout then
996
+ Python's default timeout for sockets will be used. See for example
997
+ the docs of socket.setdefaulttimeout():
998
+ http://docs.python.org/library/socket.html#socket.setdefaulttimeout
999
+ """
1000
+ def __init__(self, host, port=None, key_file=None, cert_file=None,
1001
+ strict=None, timeout=None, proxy_info=None,
1002
+ ca_certs=None, disable_ssl_certificate_validation=False,
1003
+ ssl_version=None):
1004
+ httplib.HTTPSConnection.__init__(self, host, port=port,
1005
+ key_file=key_file,
1006
+ cert_file=cert_file, strict=strict)
1007
+ self.timeout = timeout
1008
+ self.proxy_info = proxy_info
1009
+ if ca_certs is None:
1010
+ ca_certs = CA_CERTS
1011
+ self.ca_certs = ca_certs
1012
+ self.disable_ssl_certificate_validation = \
1013
+ disable_ssl_certificate_validation
1014
+ self.ssl_version = ssl_version
1015
+
1016
+ # The following two methods were adapted from https_wrapper.py, released
1017
+ # with the Google Appengine SDK at
1018
+ # http://googleappengine.googlecode.com/svn-history/r136/trunk/python/google/appengine/tools/https_wrapper.py
1019
+ # under the following license:
1020
+ #
1021
+ # Copyright 2007 Google Inc.
1022
+ #
1023
+ # Licensed under the Apache License, Version 2.0 (the "License");
1024
+ # you may not use this file except in compliance with the License.
1025
+ # You may obtain a copy of the License at
1026
+ #
1027
+ # http://www.apache.org/licenses/LICENSE-2.0
1028
+ #
1029
+ # Unless required by applicable law or agreed to in writing, software
1030
+ # distributed under the License is distributed on an "AS IS" BASIS,
1031
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1032
+ # See the License for the specific language governing permissions and
1033
+ # limitations under the License.
1034
+ #
1035
+
1036
+ def _GetValidHostsForCert(self, cert):
1037
+ """Returns a list of valid host globs for an SSL certificate.
1038
+
1039
+ Args:
1040
+ cert: A dictionary representing an SSL certificate.
1041
+ Returns:
1042
+ list: A list of valid host globs.
1043
+ """
1044
+ if 'subjectAltName' in cert:
1045
+ return [x[1] for x in cert['subjectAltName']
1046
+ if x[0].lower() == 'dns']
1047
+ else:
1048
+ return [x[0][1] for x in cert['subject']
1049
+ if x[0][0].lower() == 'commonname']
1050
+
1051
+ def _ValidateCertificateHostname(self, cert, hostname):
1052
+ """Validates that a given hostname is valid for an SSL certificate.
1053
+
1054
+ Args:
1055
+ cert: A dictionary representing an SSL certificate.
1056
+ hostname: The hostname to test.
1057
+ Returns:
1058
+ bool: Whether or not the hostname is valid for this certificate.
1059
+ """
1060
+ hosts = self._GetValidHostsForCert(cert)
1061
+ for host in hosts:
1062
+ host_re = host.replace('.', '\.').replace('*', '[^.]*')
1063
+ if re.search('^%s$' % (host_re,), hostname, re.I):
1064
+ return True
1065
+ return False
1066
+
1067
+ def connect(self):
1068
+ "Connect to a host on a given (SSL) port."
1069
+
1070
+ msg = "getaddrinfo returns an empty list"
1071
+ if self.proxy_info and self.proxy_info.isgood():
1072
+ use_proxy = True
1073
+ proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers = self.proxy_info.astuple()
1074
+
1075
+ host = proxy_host
1076
+ port = proxy_port
1077
+ else:
1078
+ use_proxy = False
1079
+
1080
+ host = self.host
1081
+ port = self.port
1082
+
1083
+ address_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
1084
+ for family, socktype, proto, canonname, sockaddr in address_info:
1085
+ try:
1086
+ if use_proxy:
1087
+ sock = socks.socksocket(family, socktype, proto)
1088
+
1089
+ sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)
1090
+ else:
1091
+ sock = socket.socket(family, socktype, proto)
1092
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
1093
+
1094
+ if has_timeout(self.timeout):
1095
+ sock.settimeout(self.timeout)
1096
+
1097
+ if use_proxy:
1098
+ sock.connect((self.host, self.port) + sockaddr[:2])
1099
+ else:
1100
+ sock.connect(sockaddr)
1101
+ self.sock =_ssl_wrap_socket(
1102
+ sock, self.key_file, self.cert_file,
1103
+ self.disable_ssl_certificate_validation, self.ca_certs,
1104
+ self.ssl_version, self.host)
1105
+ if self.debuglevel > 0:
1106
+ print("connect: (%s, %s)" % (self.host, self.port))
1107
+ if use_proxy:
1108
+ print("proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)))
1109
+ if not self.disable_ssl_certificate_validation:
1110
+ cert = self.sock.getpeercert()
1111
+ hostname = self.host.split(':', 0)[0]
1112
+ if not self._ValidateCertificateHostname(cert, hostname):
1113
+ raise CertificateHostnameMismatch(
1114
+ 'Server presented certificate that does not match '
1115
+ 'host %s: %s' % (hostname, cert), hostname, cert)
1116
+ except (ssl_SSLError, ssl_CertificateError, CertificateHostnameMismatch) as e:
1117
+ if sock:
1118
+ sock.close()
1119
+ if self.sock:
1120
+ self.sock.close()
1121
+ self.sock = None
1122
+ # Unfortunately the ssl module doesn't seem to provide any way
1123
+ # to get at more detailed error information, in particular
1124
+ # whether the error is due to certificate validation or
1125
+ # something else (such as SSL protocol mismatch).
1126
+ if getattr(e, 'errno', None) == ssl.SSL_ERROR_SSL:
1127
+ raise SSLHandshakeError(e)
1128
+ else:
1129
+ raise
1130
+ except (socket.timeout, socket.gaierror):
1131
+ raise
1132
+ except socket.error as msg:
1133
+ if self.debuglevel > 0:
1134
+ print("connect fail: (%s, %s)" % (self.host, self.port))
1135
+ if use_proxy:
1136
+ print("proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)))
1137
+ if self.sock:
1138
+ self.sock.close()
1139
+ self.sock = None
1140
+ continue
1141
+ break
1142
+ if not self.sock:
1143
+ raise socket.error, msg
1144
+
1145
+ SCHEME_TO_CONNECTION = {
1146
+ 'http': HTTPConnectionWithTimeout,
1147
+ 'https': HTTPSConnectionWithTimeout
1148
+ }
1149
+
1150
+
1151
+ def _new_fixed_fetch(validate_certificate):
1152
+ def fixed_fetch(url, payload=None, method="GET", headers={},
1153
+ allow_truncated=False, follow_redirects=True,
1154
+ deadline=None):
1155
+ if deadline is None:
1156
+ deadline = socket.getdefaulttimeout()
1157
+ return fetch(url, payload=payload, method=method, headers=headers,
1158
+ allow_truncated=allow_truncated,
1159
+ follow_redirects=follow_redirects, deadline=deadline,
1160
+ validate_certificate=validate_certificate)
1161
+ return fixed_fetch
1162
+
1163
+
1164
+ class AppEngineHttpConnection(httplib.HTTPConnection):
1165
+ """Use httplib on App Engine, but compensate for its weirdness.
1166
+
1167
+ The parameters key_file, cert_file, proxy_info, ca_certs,
1168
+ disable_ssl_certificate_validation, and ssl_version are all dropped on
1169
+ the ground.
1170
+ """
1171
+ def __init__(self, host, port=None, key_file=None, cert_file=None,
1172
+ strict=None, timeout=None, proxy_info=None, ca_certs=None,
1173
+ disable_ssl_certificate_validation=False,
1174
+ ssl_version=None):
1175
+ httplib.HTTPConnection.__init__(self, host, port=port,
1176
+ strict=strict, timeout=timeout)
1177
+
1178
+
1179
+ class AppEngineHttpsConnection(httplib.HTTPSConnection):
1180
+ """Same as AppEngineHttpConnection, but for HTTPS URIs.
1181
+
1182
+ The parameters proxy_info, ca_certs, disable_ssl_certificate_validation,
1183
+ and ssl_version are all dropped on the ground.
1184
+ """
1185
+ def __init__(self, host, port=None, key_file=None, cert_file=None,
1186
+ strict=None, timeout=None, proxy_info=None, ca_certs=None,
1187
+ disable_ssl_certificate_validation=False,
1188
+ ssl_version=None):
1189
+ httplib.HTTPSConnection.__init__(self, host, port=port,
1190
+ key_file=key_file,
1191
+ cert_file=cert_file, strict=strict,
1192
+ timeout=timeout)
1193
+ self._fetch = _new_fixed_fetch(
1194
+ not disable_ssl_certificate_validation)
1195
+
1196
+ # Use a different connection object for Google App Engine
1197
+ try:
1198
+ server_software = os.environ.get('SERVER_SOFTWARE')
1199
+ if not server_software:
1200
+ raise NotRunningAppEngineEnvironment()
1201
+ elif not (server_software.startswith('Google App Engine/') or
1202
+ server_software.startswith('Development/')):
1203
+ raise NotRunningAppEngineEnvironment()
1204
+
1205
+ from google.appengine.api import apiproxy_stub_map
1206
+ if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None:
1207
+ raise ImportError # Bail out; we're not actually running on App Engine.
1208
+ from google.appengine.api.urlfetch import fetch
1209
+ from google.appengine.api.urlfetch import InvalidURLError
1210
+
1211
+ # Update the connection classes to use the Googel App Engine specific ones.
1212
+ SCHEME_TO_CONNECTION = {
1213
+ 'http': AppEngineHttpConnection,
1214
+ 'https': AppEngineHttpsConnection
1215
+ }
1216
+ except (ImportError, AttributeError, NotRunningAppEngineEnvironment):
1217
+ pass
1218
+
1219
+
1220
+ class Http(object):
1221
+ """An HTTP client that handles:
1222
+
1223
+ - all methods
1224
+ - caching
1225
+ - ETags
1226
+ - compression,
1227
+ - HTTPS
1228
+ - Basic
1229
+ - Digest
1230
+ - WSSE
1231
+
1232
+ and more.
1233
+ """
1234
+ def __init__(self, cache=None, timeout=None,
1235
+ proxy_info=proxy_info_from_environment,
1236
+ ca_certs=None, disable_ssl_certificate_validation=False,
1237
+ ssl_version=None):
1238
+ """If 'cache' is a string then it is used as a directory name for
1239
+ a disk cache. Otherwise it must be an object that supports the
1240
+ same interface as FileCache.
1241
+
1242
+ All timeouts are in seconds. If None is passed for timeout
1243
+ then Python's default timeout for sockets will be used. See
1244
+ for example the docs of socket.setdefaulttimeout():
1245
+ http://docs.python.org/library/socket.html#socket.setdefaulttimeout
1246
+
1247
+ `proxy_info` may be:
1248
+ - a callable that takes the http scheme ('http' or 'https') and
1249
+ returns a ProxyInfo instance per request. By default, uses
1250
+ proxy_nfo_from_environment.
1251
+ - a ProxyInfo instance (static proxy config).
1252
+ - None (proxy disabled).
1253
+
1254
+ ca_certs is the path of a file containing root CA certificates for SSL
1255
+ server certificate validation. By default, a CA cert file bundled with
1256
+ httplib2 is used.
1257
+
1258
+ If disable_ssl_certificate_validation is true, SSL cert validation will
1259
+ not be performed.
1260
+
1261
+ By default, ssl.PROTOCOL_SSLv23 will be used for the ssl version.
1262
+ """
1263
+ self.proxy_info = proxy_info
1264
+ self.ca_certs = ca_certs
1265
+ self.disable_ssl_certificate_validation = \
1266
+ disable_ssl_certificate_validation
1267
+ self.ssl_version = ssl_version
1268
+
1269
+ # Map domain name to an httplib connection
1270
+ self.connections = {}
1271
+ # The location of the cache, for now a directory
1272
+ # where cached responses are held.
1273
+ if cache and isinstance(cache, basestring):
1274
+ self.cache = FileCache(cache)
1275
+ else:
1276
+ self.cache = cache
1277
+
1278
+ # Name/password
1279
+ self.credentials = Credentials()
1280
+
1281
+ # Key/cert
1282
+ self.certificates = KeyCerts()
1283
+
1284
+ # authorization objects
1285
+ self.authorizations = []
1286
+
1287
+ # If set to False then no redirects are followed, even safe ones.
1288
+ self.follow_redirects = True
1289
+
1290
+ # Which HTTP methods do we apply optimistic concurrency to, i.e.
1291
+ # which methods get an "if-match:" etag header added to them.
1292
+ self.optimistic_concurrency_methods = ["PUT", "PATCH"]
1293
+
1294
+ # If 'follow_redirects' is True, and this is set to True then
1295
+ # all redirecs are followed, including unsafe ones.
1296
+ self.follow_all_redirects = False
1297
+
1298
+ self.ignore_etag = False
1299
+
1300
+ self.force_exception_to_status_code = False
1301
+
1302
+ self.timeout = timeout
1303
+
1304
+ # Keep Authorization: headers on a redirect.
1305
+ self.forward_authorization_headers = False
1306
+
1307
+ def __getstate__(self):
1308
+ state_dict = copy.copy(self.__dict__)
1309
+ # In case request is augmented by some foreign object such as
1310
+ # credentials which handle auth
1311
+ if 'request' in state_dict:
1312
+ del state_dict['request']
1313
+ if 'connections' in state_dict:
1314
+ del state_dict['connections']
1315
+ return state_dict
1316
+
1317
+ def __setstate__(self, state):
1318
+ self.__dict__.update(state)
1319
+ self.connections = {}
1320
+
1321
+ def _auth_from_challenge(self, host, request_uri, headers, response, content):
1322
+ """A generator that creates Authorization objects
1323
+ that can be applied to requests.
1324
+ """
1325
+ challenges = _parse_www_authenticate(response, 'www-authenticate')
1326
+ for cred in self.credentials.iter(host):
1327
+ for scheme in AUTH_SCHEME_ORDER:
1328
+ if scheme in challenges:
1329
+ yield AUTH_SCHEME_CLASSES[scheme](cred, host, request_uri, headers, response, content, self)
1330
+
1331
+ def add_credentials(self, name, password, domain=""):
1332
+ """Add a name and password that will be used
1333
+ any time a request requires authentication."""
1334
+ self.credentials.add(name, password, domain)
1335
+
1336
+ def add_certificate(self, key, cert, domain):
1337
+ """Add a key and cert that will be used
1338
+ any time a request requires authentication."""
1339
+ self.certificates.add(key, cert, domain)
1340
+
1341
+ def clear_credentials(self):
1342
+ """Remove all the names and passwords
1343
+ that are used for authentication"""
1344
+ self.credentials.clear()
1345
+ self.authorizations = []
1346
+
1347
+ def _conn_request(self, conn, request_uri, method, body, headers):
1348
+ i = 0
1349
+ seen_bad_status_line = False
1350
+ while i < RETRIES:
1351
+ i += 1
1352
+ try:
1353
+ if hasattr(conn, 'sock') and conn.sock is None:
1354
+ conn.connect()
1355
+ conn.request(method, request_uri, body, headers)
1356
+ except socket.timeout:
1357
+ raise
1358
+ except socket.gaierror:
1359
+ conn.close()
1360
+ raise ServerNotFoundError("Unable to find the server at %s" % conn.host)
1361
+ except ssl_SSLError:
1362
+ conn.close()
1363
+ raise
1364
+ except socket.error as e:
1365
+ err = 0
1366
+ if hasattr(e, 'args'):
1367
+ err = getattr(e, 'args')[0]
1368
+ else:
1369
+ err = e.errno
1370
+ if err == errno.ECONNREFUSED: # Connection refused
1371
+ raise
1372
+ if err in (errno.ENETUNREACH, errno.EADDRNOTAVAIL) and i < RETRIES:
1373
+ continue # retry on potentially transient socket errors
1374
+ except httplib.HTTPException:
1375
+ # Just because the server closed the connection doesn't apparently mean
1376
+ # that the server didn't send a response.
1377
+ if hasattr(conn, 'sock') and conn.sock is None:
1378
+ if i < RETRIES-1:
1379
+ conn.close()
1380
+ conn.connect()
1381
+ continue
1382
+ else:
1383
+ conn.close()
1384
+ raise
1385
+ if i < RETRIES-1:
1386
+ conn.close()
1387
+ conn.connect()
1388
+ continue
1389
+ try:
1390
+ response = conn.getresponse()
1391
+ except httplib.BadStatusLine:
1392
+ # If we get a BadStatusLine on the first try then that means
1393
+ # the connection just went stale, so retry regardless of the
1394
+ # number of RETRIES set.
1395
+ if not seen_bad_status_line and i == 1:
1396
+ i = 0
1397
+ seen_bad_status_line = True
1398
+ conn.close()
1399
+ conn.connect()
1400
+ continue
1401
+ else:
1402
+ conn.close()
1403
+ raise
1404
+ except (socket.error, httplib.HTTPException):
1405
+ if i < RETRIES-1:
1406
+ conn.close()
1407
+ conn.connect()
1408
+ continue
1409
+ else:
1410
+ conn.close()
1411
+ raise
1412
+ else:
1413
+ content = ""
1414
+ if method == "HEAD":
1415
+ conn.close()
1416
+ else:
1417
+ content = response.read()
1418
+ response = Response(response)
1419
+ if method != "HEAD":
1420
+ content = _decompressContent(response, content)
1421
+ break
1422
+ return (response, content)
1423
+
1424
+
1425
+ def _request(self, conn, host, absolute_uri, request_uri, method, body, headers, redirections, cachekey):
1426
+ """Do the actual request using the connection object
1427
+ and also follow one level of redirects if necessary"""
1428
+
1429
+ auths = [(auth.depth(request_uri), auth) for auth in self.authorizations if auth.inscope(host, request_uri)]
1430
+ auth = auths and sorted(auths)[0][1] or None
1431
+ if auth:
1432
+ auth.request(method, request_uri, headers, body)
1433
+
1434
+ (response, content) = self._conn_request(conn, request_uri, method, body, headers)
1435
+
1436
+ if auth:
1437
+ if auth.response(response, body):
1438
+ auth.request(method, request_uri, headers, body)
1439
+ (response, content) = self._conn_request(conn, request_uri, method, body, headers )
1440
+ response._stale_digest = 1
1441
+
1442
+ if response.status == 401:
1443
+ for authorization in self._auth_from_challenge(host, request_uri, headers, response, content):
1444
+ authorization.request(method, request_uri, headers, body)
1445
+ (response, content) = self._conn_request(conn, request_uri, method, body, headers, )
1446
+ if response.status != 401:
1447
+ self.authorizations.append(authorization)
1448
+ authorization.response(response, body)
1449
+ break
1450
+
1451
+ if (self.follow_all_redirects or (method in ["GET", "HEAD"]) or response.status == 303):
1452
+ if self.follow_redirects and response.status in [300, 301, 302, 303, 307]:
1453
+ # Pick out the location header and basically start from the beginning
1454
+ # remembering first to strip the ETag header and decrement our 'depth'
1455
+ if redirections:
1456
+ if 'location' not in response and response.status != 300:
1457
+ raise RedirectMissingLocation( _("Redirected but the response is missing a Location: header."), response, content)
1458
+ # Fix-up relative redirects (which violate an RFC 2616 MUST)
1459
+ if 'location' in response:
1460
+ location = response['location']
1461
+ (scheme, authority, path, query, fragment) = parse_uri(location)
1462
+ if authority == None:
1463
+ response['location'] = urlparse.urljoin(absolute_uri, location)
1464
+ if response.status == 301 and method in ["GET", "HEAD"]:
1465
+ response['-x-permanent-redirect-url'] = response['location']
1466
+ if 'content-location' not in response:
1467
+ response['content-location'] = absolute_uri
1468
+ _updateCache(headers, response, content, self.cache, cachekey)
1469
+ if 'if-none-match' in headers:
1470
+ del headers['if-none-match']
1471
+ if 'if-modified-since' in headers:
1472
+ del headers['if-modified-since']
1473
+ if 'authorization' in headers and not self.forward_authorization_headers:
1474
+ del headers['authorization']
1475
+ if 'location' in response:
1476
+ location = response['location']
1477
+ old_response = copy.deepcopy(response)
1478
+ if 'content-location' not in old_response:
1479
+ old_response['content-location'] = absolute_uri
1480
+ redirect_method = method
1481
+ if response.status in [302, 303]:
1482
+ redirect_method = "GET"
1483
+ body = None
1484
+ (response, content) = self.request(
1485
+ location, method=redirect_method,
1486
+ body=body, headers=headers,
1487
+ redirections=redirections - 1)
1488
+ response.previous = old_response
1489
+ else:
1490
+ raise RedirectLimit("Redirected more times than rediection_limit allows.", response, content)
1491
+ elif response.status in [200, 203] and method in ["GET", "HEAD"]:
1492
+ # Don't cache 206's since we aren't going to handle byte range requests
1493
+ if 'content-location' not in response:
1494
+ response['content-location'] = absolute_uri
1495
+ _updateCache(headers, response, content, self.cache, cachekey)
1496
+
1497
+ return (response, content)
1498
+
1499
+ def _normalize_headers(self, headers):
1500
+ return _normalize_headers(headers)
1501
+
1502
+ # Need to catch and rebrand some exceptions
1503
+ # Then need to optionally turn all exceptions into status codes
1504
+ # including all socket.* and httplib.* exceptions.
1505
+
1506
+
1507
+ def request(self, uri, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None):
1508
+ """ Performs a single HTTP request.
1509
+
1510
+ The 'uri' is the URI of the HTTP resource and can begin with either
1511
+ 'http' or 'https'. The value of 'uri' must be an absolute URI.
1512
+
1513
+ The 'method' is the HTTP method to perform, such as GET, POST, DELETE,
1514
+ etc. There is no restriction on the methods allowed.
1515
+
1516
+ The 'body' is the entity body to be sent with the request. It is a
1517
+ string object.
1518
+
1519
+ Any extra headers that are to be sent with the request should be
1520
+ provided in the 'headers' dictionary.
1521
+
1522
+ The maximum number of redirect to follow before raising an
1523
+ exception is 'redirections. The default is 5.
1524
+
1525
+ The return value is a tuple of (response, content), the first
1526
+ being and instance of the 'Response' class, the second being
1527
+ a string that contains the response entity body.
1528
+ """
1529
+ try:
1530
+ if headers is None:
1531
+ headers = {}
1532
+ else:
1533
+ headers = self._normalize_headers(headers)
1534
+
1535
+ if 'user-agent' not in headers:
1536
+ headers['user-agent'] = "Python-httplib2/%s (gzip)" % __version__
1537
+
1538
+ uri = iri2uri(uri)
1539
+
1540
+ (scheme, authority, request_uri, defrag_uri) = urlnorm(uri)
1541
+ domain_port = authority.split(":")[0:2]
1542
+ if len(domain_port) == 2 and domain_port[1] == '443' and scheme == 'http':
1543
+ scheme = 'https'
1544
+ authority = domain_port[0]
1545
+
1546
+ proxy_info = self._get_proxy_info(scheme, authority)
1547
+
1548
+ conn_key = scheme+":"+authority
1549
+ if conn_key in self.connections:
1550
+ conn = self.connections[conn_key]
1551
+ else:
1552
+ if not connection_type:
1553
+ connection_type = SCHEME_TO_CONNECTION[scheme]
1554
+ certs = list(self.certificates.iter(authority))
1555
+ if scheme == 'https':
1556
+ if certs:
1557
+ conn = self.connections[conn_key] = connection_type(
1558
+ authority, key_file=certs[0][0],
1559
+ cert_file=certs[0][1], timeout=self.timeout,
1560
+ proxy_info=proxy_info,
1561
+ ca_certs=self.ca_certs,
1562
+ disable_ssl_certificate_validation=
1563
+ self.disable_ssl_certificate_validation,
1564
+ ssl_version=self.ssl_version)
1565
+ else:
1566
+ conn = self.connections[conn_key] = connection_type(
1567
+ authority, timeout=self.timeout,
1568
+ proxy_info=proxy_info,
1569
+ ca_certs=self.ca_certs,
1570
+ disable_ssl_certificate_validation=
1571
+ self.disable_ssl_certificate_validation,
1572
+ ssl_version=self.ssl_version)
1573
+ else:
1574
+ conn = self.connections[conn_key] = connection_type(
1575
+ authority, timeout=self.timeout,
1576
+ proxy_info=proxy_info)
1577
+ conn.set_debuglevel(debuglevel)
1578
+
1579
+ if 'range' not in headers and 'accept-encoding' not in headers:
1580
+ headers['accept-encoding'] = 'gzip, deflate'
1581
+
1582
+ info = email.Message.Message()
1583
+ cached_value = None
1584
+ if self.cache:
1585
+ cachekey = defrag_uri.encode('utf-8')
1586
+ cached_value = self.cache.get(cachekey)
1587
+ if cached_value:
1588
+ # info = email.message_from_string(cached_value)
1589
+ #
1590
+ # Need to replace the line above with the kludge below
1591
+ # to fix the non-existent bug not fixed in this
1592
+ # bug report: http://mail.python.org/pipermail/python-bugs-list/2005-September/030289.html
1593
+ try:
1594
+ info, content = cached_value.split('\r\n\r\n', 1)
1595
+ feedparser = email.FeedParser.FeedParser()
1596
+ feedparser.feed(info)
1597
+ info = feedparser.close()
1598
+ feedparser._parse = None
1599
+ except (IndexError, ValueError):
1600
+ self.cache.delete(cachekey)
1601
+ cachekey = None
1602
+ cached_value = None
1603
+ else:
1604
+ cachekey = None
1605
+
1606
+ if method in self.optimistic_concurrency_methods and self.cache and 'etag' in info and not self.ignore_etag and 'if-match' not in headers:
1607
+ # http://www.w3.org/1999/04/Editing/
1608
+ headers['if-match'] = info['etag']
1609
+
1610
+ if method not in ["GET", "HEAD"] and self.cache and cachekey:
1611
+ # RFC 2616 Section 13.10
1612
+ self.cache.delete(cachekey)
1613
+
1614
+ # Check the vary header in the cache to see if this request
1615
+ # matches what varies in the cache.
1616
+ if method in ['GET', 'HEAD'] and 'vary' in info:
1617
+ vary = info['vary']
1618
+ vary_headers = vary.lower().replace(' ', '').split(',')
1619
+ for header in vary_headers:
1620
+ key = '-varied-%s' % header
1621
+ value = info[key]
1622
+ if headers.get(header, None) != value:
1623
+ cached_value = None
1624
+ break
1625
+
1626
+ if cached_value and method in ["GET", "HEAD"] and self.cache and 'range' not in headers:
1627
+ if '-x-permanent-redirect-url' in info:
1628
+ # Should cached permanent redirects be counted in our redirection count? For now, yes.
1629
+ if redirections <= 0:
1630
+ raise RedirectLimit("Redirected more times than rediection_limit allows.", {}, "")
1631
+ (response, new_content) = self.request(
1632
+ info['-x-permanent-redirect-url'], method='GET',
1633
+ headers=headers, redirections=redirections - 1)
1634
+ response.previous = Response(info)
1635
+ response.previous.fromcache = True
1636
+ else:
1637
+ # Determine our course of action:
1638
+ # Is the cached entry fresh or stale?
1639
+ # Has the client requested a non-cached response?
1640
+ #
1641
+ # There seems to be three possible answers:
1642
+ # 1. [FRESH] Return the cache entry w/o doing a GET
1643
+ # 2. [STALE] Do the GET (but add in cache validators if available)
1644
+ # 3. [TRANSPARENT] Do a GET w/o any cache validators (Cache-Control: no-cache) on the request
1645
+ entry_disposition = _entry_disposition(info, headers)
1646
+
1647
+ if entry_disposition == "FRESH":
1648
+ if not cached_value:
1649
+ info['status'] = '504'
1650
+ content = ""
1651
+ response = Response(info)
1652
+ if cached_value:
1653
+ response.fromcache = True
1654
+ return (response, content)
1655
+
1656
+ if entry_disposition == "STALE":
1657
+ if 'etag' in info and not self.ignore_etag and not 'if-none-match' in headers:
1658
+ headers['if-none-match'] = info['etag']
1659
+ if 'last-modified' in info and not 'last-modified' in headers:
1660
+ headers['if-modified-since'] = info['last-modified']
1661
+ elif entry_disposition == "TRANSPARENT":
1662
+ pass
1663
+
1664
+ (response, new_content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
1665
+
1666
+ if response.status == 304 and method == "GET":
1667
+ # Rewrite the cache entry with the new end-to-end headers
1668
+ # Take all headers that are in response
1669
+ # and overwrite their values in info.
1670
+ # unless they are hop-by-hop, or are listed in the connection header.
1671
+
1672
+ for key in _get_end2end_headers(response):
1673
+ info[key] = response[key]
1674
+ merged_response = Response(info)
1675
+ if hasattr(response, "_stale_digest"):
1676
+ merged_response._stale_digest = response._stale_digest
1677
+ _updateCache(headers, merged_response, content, self.cache, cachekey)
1678
+ response = merged_response
1679
+ response.status = 200
1680
+ response.fromcache = True
1681
+
1682
+ elif response.status == 200:
1683
+ content = new_content
1684
+ else:
1685
+ self.cache.delete(cachekey)
1686
+ content = new_content
1687
+ else:
1688
+ cc = _parse_cache_control(headers)
1689
+ if 'only-if-cached' in cc:
1690
+ info['status'] = '504'
1691
+ response = Response(info)
1692
+ content = ""
1693
+ else:
1694
+ (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
1695
+ except Exception as e:
1696
+ if self.force_exception_to_status_code:
1697
+ if isinstance(e, HttpLib2ErrorWithResponse):
1698
+ response = e.response
1699
+ content = e.content
1700
+ response.status = 500
1701
+ response.reason = str(e)
1702
+ elif isinstance(e, socket.timeout):
1703
+ content = "Request Timeout"
1704
+ response = Response({
1705
+ "content-type": "text/plain",
1706
+ "status": "408",
1707
+ "content-length": len(content)
1708
+ })
1709
+ response.reason = "Request Timeout"
1710
+ else:
1711
+ content = str(e)
1712
+ response = Response({
1713
+ "content-type": "text/plain",
1714
+ "status": "400",
1715
+ "content-length": len(content)
1716
+ })
1717
+ response.reason = "Bad Request"
1718
+ else:
1719
+ raise
1720
+
1721
+
1722
+ return (response, content)
1723
+
1724
+ def _get_proxy_info(self, scheme, authority):
1725
+ """Return a ProxyInfo instance (or None) based on the scheme
1726
+ and authority.
1727
+ """
1728
+ hostname, port = urllib.splitport(authority)
1729
+ proxy_info = self.proxy_info
1730
+ if callable(proxy_info):
1731
+ proxy_info = proxy_info(scheme)
1732
+
1733
+ if (hasattr(proxy_info, 'applies_to')
1734
+ and not proxy_info.applies_to(hostname)):
1735
+ proxy_info = None
1736
+ return proxy_info
1737
+
1738
+
1739
+ class Response(dict):
1740
+ """An object more like email.Message than httplib.HTTPResponse."""
1741
+
1742
+ """Is this response from our local cache"""
1743
+ fromcache = False
1744
+
1745
+ """HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1. """
1746
+ version = 11
1747
+
1748
+ "Status code returned by server. "
1749
+ status = 200
1750
+
1751
+ """Reason phrase returned by server."""
1752
+ reason = "Ok"
1753
+
1754
+ previous = None
1755
+
1756
+ def __init__(self, info):
1757
+ # info is either an email.Message or
1758
+ # an httplib.HTTPResponse object.
1759
+ if isinstance(info, httplib.HTTPResponse):
1760
+ for key, value in info.getheaders():
1761
+ self[key.lower()] = value
1762
+ self.status = info.status
1763
+ self['status'] = str(self.status)
1764
+ self.reason = info.reason
1765
+ self.version = info.version
1766
+ elif isinstance(info, email.Message.Message):
1767
+ for key, value in info.items():
1768
+ self[key.lower()] = value
1769
+ self.status = int(self['status'])
1770
+ else:
1771
+ for key, value in info.iteritems():
1772
+ self[key.lower()] = value
1773
+ self.status = int(self.get('status', self.status))
1774
+ self.reason = self.get('reason', self.reason)
1775
+
1776
+ def __getattr__(self, name):
1777
+ if name == 'dict':
1778
+ return self
1779
+ else:
1780
+ raise AttributeError(name)