libv8 8.4.255.0

Sign up to get free protection for your applications and to get access to all the features.
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)