busser-behave 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. checksums.yaml +7 -0
  2. data/.cane +0 -0
  3. data/.gitignore +17 -0
  4. data/.tailor +4 -0
  5. data/.travis.yml +11 -0
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +15 -0
  9. data/README.md +41 -0
  10. data/Rakefile +68 -0
  11. data/busser-behave.gemspec +30 -0
  12. data/features/plugin_install_command.feature +11 -0
  13. data/features/plugin_list_command.feature +8 -0
  14. data/features/support/env.rb +13 -0
  15. data/features/test_command.feature +31 -0
  16. data/lib/busser/behave/version.rb +26 -0
  17. data/lib/busser/runner_plugin/behave.rb +37 -0
  18. data/vendor/behave/CHANGES.rst +483 -0
  19. data/vendor/behave/LICENSE +23 -0
  20. data/vendor/behave/MANIFEST.in +37 -0
  21. data/vendor/behave/PROJECT_INFO.rst +21 -0
  22. data/vendor/behave/README.rst +112 -0
  23. data/vendor/behave/VERSION.txt +1 -0
  24. data/vendor/behave/behave.ini +22 -0
  25. data/vendor/behave/behave/__init__.py +30 -0
  26. data/vendor/behave/behave/__main__.py +187 -0
  27. data/vendor/behave/behave/_stepimport.py +185 -0
  28. data/vendor/behave/behave/_types.py +134 -0
  29. data/vendor/behave/behave/api/__init__.py +7 -0
  30. data/vendor/behave/behave/api/async_step.py +283 -0
  31. data/vendor/behave/behave/capture.py +227 -0
  32. data/vendor/behave/behave/compat/__init__.py +5 -0
  33. data/vendor/behave/behave/compat/collections.py +20 -0
  34. data/vendor/behave/behave/configuration.py +788 -0
  35. data/vendor/behave/behave/contrib/__init__.py +0 -0
  36. data/vendor/behave/behave/contrib/scenario_autoretry.py +73 -0
  37. data/vendor/behave/behave/formatter/__init__.py +12 -0
  38. data/vendor/behave/behave/formatter/_builtins.py +39 -0
  39. data/vendor/behave/behave/formatter/_registry.py +135 -0
  40. data/vendor/behave/behave/formatter/ansi_escapes.py +91 -0
  41. data/vendor/behave/behave/formatter/base.py +200 -0
  42. data/vendor/behave/behave/formatter/formatters.py +57 -0
  43. data/vendor/behave/behave/formatter/json.py +253 -0
  44. data/vendor/behave/behave/formatter/null.py +12 -0
  45. data/vendor/behave/behave/formatter/plain.py +158 -0
  46. data/vendor/behave/behave/formatter/pretty.py +351 -0
  47. data/vendor/behave/behave/formatter/progress.py +287 -0
  48. data/vendor/behave/behave/formatter/rerun.py +114 -0
  49. data/vendor/behave/behave/formatter/sphinx_steps.py +372 -0
  50. data/vendor/behave/behave/formatter/sphinx_util.py +118 -0
  51. data/vendor/behave/behave/formatter/steps.py +497 -0
  52. data/vendor/behave/behave/formatter/tags.py +178 -0
  53. data/vendor/behave/behave/i18n.py +614 -0
  54. data/vendor/behave/behave/importer.py +102 -0
  55. data/vendor/behave/behave/json_parser.py +264 -0
  56. data/vendor/behave/behave/log_capture.py +233 -0
  57. data/vendor/behave/behave/matchers.py +402 -0
  58. data/vendor/behave/behave/model.py +1737 -0
  59. data/vendor/behave/behave/model_core.py +416 -0
  60. data/vendor/behave/behave/model_describe.py +105 -0
  61. data/vendor/behave/behave/parser.py +615 -0
  62. data/vendor/behave/behave/reporter/__init__.py +0 -0
  63. data/vendor/behave/behave/reporter/base.py +45 -0
  64. data/vendor/behave/behave/reporter/junit.py +473 -0
  65. data/vendor/behave/behave/reporter/summary.py +94 -0
  66. data/vendor/behave/behave/runner.py +753 -0
  67. data/vendor/behave/behave/runner_util.py +417 -0
  68. data/vendor/behave/behave/step_registry.py +112 -0
  69. data/vendor/behave/behave/tag_expression.py +111 -0
  70. data/vendor/behave/behave/tag_matcher.py +465 -0
  71. data/vendor/behave/behave/textutil.py +137 -0
  72. data/vendor/behave/behave/userdata.py +130 -0
  73. data/vendor/behave/behave4cmd0/__all_steps__.py +12 -0
  74. data/vendor/behave/behave4cmd0/__init__.py +5 -0
  75. data/vendor/behave/behave4cmd0/__setup.py +11 -0
  76. data/vendor/behave/behave4cmd0/command_shell.py +216 -0
  77. data/vendor/behave/behave4cmd0/command_shell_proc.py +256 -0
  78. data/vendor/behave/behave4cmd0/command_steps.py +532 -0
  79. data/vendor/behave/behave4cmd0/command_util.py +147 -0
  80. data/vendor/behave/behave4cmd0/failing_steps.py +49 -0
  81. data/vendor/behave/behave4cmd0/log/__init__.py +1 -0
  82. data/vendor/behave/behave4cmd0/log/steps.py +395 -0
  83. data/vendor/behave/behave4cmd0/note_steps.py +29 -0
  84. data/vendor/behave/behave4cmd0/passing_steps.py +36 -0
  85. data/vendor/behave/behave4cmd0/pathutil.py +146 -0
  86. data/vendor/behave/behave4cmd0/setup_command_shell.py +24 -0
  87. data/vendor/behave/behave4cmd0/textutil.py +304 -0
  88. data/vendor/behave/bin/behave +44 -0
  89. data/vendor/behave/bin/behave.cmd +10 -0
  90. data/vendor/behave/bin/behave.junit_filter.py +85 -0
  91. data/vendor/behave/bin/behave.step_durations.py +163 -0
  92. data/vendor/behave/bin/behave2cucumber_json.py +63 -0
  93. data/vendor/behave/bin/behave_cmd.py +44 -0
  94. data/vendor/behave/bin/convert_i18n_yaml.py +77 -0
  95. data/vendor/behave/bin/explore_platform_encoding.py +24 -0
  96. data/vendor/behave/bin/i18n.yml +621 -0
  97. data/vendor/behave/bin/invoke +8 -0
  98. data/vendor/behave/bin/invoke.cmd +9 -0
  99. data/vendor/behave/bin/json.format.py +167 -0
  100. data/vendor/behave/bin/jsonschema_validate.py +122 -0
  101. data/vendor/behave/bin/make_localpi.py +279 -0
  102. data/vendor/behave/bin/project_bootstrap.sh +30 -0
  103. data/vendor/behave/bin/toxcmd.py +270 -0
  104. data/vendor/behave/bin/toxcmd3.py +270 -0
  105. data/vendor/behave/conftest.py +27 -0
  106. data/vendor/behave/docs/Makefile +154 -0
  107. data/vendor/behave/docs/_static/agogo.css +501 -0
  108. data/vendor/behave/docs/_static/behave_logo.png +0 -0
  109. data/vendor/behave/docs/_static/behave_logo1.png +0 -0
  110. data/vendor/behave/docs/_static/behave_logo2.png +0 -0
  111. data/vendor/behave/docs/_static/behave_logo3.png +0 -0
  112. data/vendor/behave/docs/_themes/LICENSE +45 -0
  113. data/vendor/behave/docs/_themes/kr/layout.html +17 -0
  114. data/vendor/behave/docs/_themes/kr/relations.html +19 -0
  115. data/vendor/behave/docs/_themes/kr/static/flasky.css_t +480 -0
  116. data/vendor/behave/docs/_themes/kr/static/small_flask.css +90 -0
  117. data/vendor/behave/docs/_themes/kr/theme.conf +7 -0
  118. data/vendor/behave/docs/_themes/kr_small/layout.html +22 -0
  119. data/vendor/behave/docs/_themes/kr_small/static/flasky.css_t +287 -0
  120. data/vendor/behave/docs/_themes/kr_small/theme.conf +10 -0
  121. data/vendor/behave/docs/api.rst +408 -0
  122. data/vendor/behave/docs/appendix.rst +19 -0
  123. data/vendor/behave/docs/behave.rst +640 -0
  124. data/vendor/behave/docs/behave.rst-template +86 -0
  125. data/vendor/behave/docs/behave_ecosystem.rst +81 -0
  126. data/vendor/behave/docs/comparison.rst +85 -0
  127. data/vendor/behave/docs/conf.py +293 -0
  128. data/vendor/behave/docs/context_attributes.rst +66 -0
  129. data/vendor/behave/docs/django.rst +192 -0
  130. data/vendor/behave/docs/formatters.rst +61 -0
  131. data/vendor/behave/docs/gherkin.rst +673 -0
  132. data/vendor/behave/docs/index.rst +57 -0
  133. data/vendor/behave/docs/install.rst +60 -0
  134. data/vendor/behave/docs/more_info.rst +184 -0
  135. data/vendor/behave/docs/new_and_noteworthy.rst +18 -0
  136. data/vendor/behave/docs/new_and_noteworthy_v1.2.4.rst +11 -0
  137. data/vendor/behave/docs/new_and_noteworthy_v1.2.5.rst +814 -0
  138. data/vendor/behave/docs/new_and_noteworthy_v1.2.6.rst +255 -0
  139. data/vendor/behave/docs/parse_builtin_types.rst +59 -0
  140. data/vendor/behave/docs/philosophy.rst +235 -0
  141. data/vendor/behave/docs/regular_expressions.rst +71 -0
  142. data/vendor/behave/docs/related.rst +14 -0
  143. data/vendor/behave/docs/test_domains.rst +62 -0
  144. data/vendor/behave/docs/tutorial.rst +636 -0
  145. data/vendor/behave/docs/update_behave_rst.py +100 -0
  146. data/vendor/behave/etc/json/behave.json-schema +172 -0
  147. data/vendor/behave/etc/junit.xml/behave_junit.xsd +103 -0
  148. data/vendor/behave/etc/junit.xml/junit-4.xsd +92 -0
  149. data/vendor/behave/examples/async_step/README.txt +8 -0
  150. data/vendor/behave/examples/async_step/behave.ini +14 -0
  151. data/vendor/behave/examples/async_step/features/async_dispatch.feature +8 -0
  152. data/vendor/behave/examples/async_step/features/async_run.feature +6 -0
  153. data/vendor/behave/examples/async_step/features/environment.py +28 -0
  154. data/vendor/behave/examples/async_step/features/steps/async_dispatch_steps.py +26 -0
  155. data/vendor/behave/examples/async_step/features/steps/async_steps34.py +10 -0
  156. data/vendor/behave/examples/async_step/features/steps/async_steps35.py +10 -0
  157. data/vendor/behave/examples/async_step/testrun_example.async_dispatch.txt +11 -0
  158. data/vendor/behave/examples/async_step/testrun_example.async_run.txt +9 -0
  159. data/vendor/behave/examples/env_vars/README.rst +26 -0
  160. data/vendor/behave/examples/env_vars/behave.ini +15 -0
  161. data/vendor/behave/examples/env_vars/behave_run.output_example.txt +12 -0
  162. data/vendor/behave/examples/env_vars/features/env_var.feature +6 -0
  163. data/vendor/behave/examples/env_vars/features/steps/env_var_steps.py +38 -0
  164. data/vendor/behave/features/README.txt +12 -0
  165. data/vendor/behave/features/background.feature +392 -0
  166. data/vendor/behave/features/capture_stderr.feature +172 -0
  167. data/vendor/behave/features/capture_stdout.feature +125 -0
  168. data/vendor/behave/features/cmdline.lang_list.feature +33 -0
  169. data/vendor/behave/features/configuration.default_paths.feature +116 -0
  170. data/vendor/behave/features/context.global_params.feature +35 -0
  171. data/vendor/behave/features/context.local_params.feature +17 -0
  172. data/vendor/behave/features/directory_layout.advanced.feature +147 -0
  173. data/vendor/behave/features/directory_layout.basic.feature +75 -0
  174. data/vendor/behave/features/directory_layout.basic2.feature +87 -0
  175. data/vendor/behave/features/environment.py +53 -0
  176. data/vendor/behave/features/exploratory_testing.with_table.feature +141 -0
  177. data/vendor/behave/features/feature.description.feature +0 -0
  178. data/vendor/behave/features/feature.exclude_from_run.feature +96 -0
  179. data/vendor/behave/features/formatter.help.feature +30 -0
  180. data/vendor/behave/features/formatter.json.feature +420 -0
  181. data/vendor/behave/features/formatter.progress3.feature +235 -0
  182. data/vendor/behave/features/formatter.rerun.feature +296 -0
  183. data/vendor/behave/features/formatter.steps.feature +181 -0
  184. data/vendor/behave/features/formatter.steps_catalog.feature +100 -0
  185. data/vendor/behave/features/formatter.steps_doc.feature +140 -0
  186. data/vendor/behave/features/formatter.steps_usage.feature +404 -0
  187. data/vendor/behave/features/formatter.tags.feature +134 -0
  188. data/vendor/behave/features/formatter.tags_location.feature +183 -0
  189. data/vendor/behave/features/formatter.user_defined.feature +196 -0
  190. data/vendor/behave/features/i18n.unicode_problems.feature +445 -0
  191. data/vendor/behave/features/logcapture.clear_handlers.feature +114 -0
  192. data/vendor/behave/features/logcapture.feature +188 -0
  193. data/vendor/behave/features/logcapture.filter.feature +130 -0
  194. data/vendor/behave/features/logging.no_capture.feature +99 -0
  195. data/vendor/behave/features/logging.setup_format.feature +157 -0
  196. data/vendor/behave/features/logging.setup_level.feature +168 -0
  197. data/vendor/behave/features/logging.setup_with_configfile.feature +137 -0
  198. data/vendor/behave/features/parser.background.sad_cases.feature +129 -0
  199. data/vendor/behave/features/parser.feature.sad_cases.feature +144 -0
  200. data/vendor/behave/features/runner.abort_by_user.feature +305 -0
  201. data/vendor/behave/features/runner.continue_after_failed_step.feature +136 -0
  202. data/vendor/behave/features/runner.default_format.feature +175 -0
  203. data/vendor/behave/features/runner.dry_run.feature +184 -0
  204. data/vendor/behave/features/runner.feature_listfile.feature +223 -0
  205. data/vendor/behave/features/runner.hook_errors.feature +382 -0
  206. data/vendor/behave/features/runner.multiple_formatters.feature +285 -0
  207. data/vendor/behave/features/runner.scenario_autoretry.feature +131 -0
  208. data/vendor/behave/features/runner.select_files_by_regexp.example.feature +71 -0
  209. data/vendor/behave/features/runner.select_files_by_regexp.feature +84 -0
  210. data/vendor/behave/features/runner.select_scenarios_by_file_location.feature +403 -0
  211. data/vendor/behave/features/runner.select_scenarios_by_name.feature +289 -0
  212. data/vendor/behave/features/runner.select_scenarios_by_tag.feature +225 -0
  213. data/vendor/behave/features/runner.stop_after_failure.feature +122 -0
  214. data/vendor/behave/features/runner.tag_logic.feature +67 -0
  215. data/vendor/behave/features/runner.unknown_formatter.feature +23 -0
  216. data/vendor/behave/features/runner.use_stage_implementations.feature +126 -0
  217. data/vendor/behave/features/scenario.description.feature +171 -0
  218. data/vendor/behave/features/scenario.exclude_from_run.feature +217 -0
  219. data/vendor/behave/features/scenario_outline.basics.feature +100 -0
  220. data/vendor/behave/features/scenario_outline.improved.feature +177 -0
  221. data/vendor/behave/features/scenario_outline.name_annotation.feature +157 -0
  222. data/vendor/behave/features/scenario_outline.parametrized.feature +401 -0
  223. data/vendor/behave/features/scenario_outline.tagged_examples.feature +118 -0
  224. data/vendor/behave/features/step.async_steps.feature +225 -0
  225. data/vendor/behave/features/step.duplicated_step.feature +106 -0
  226. data/vendor/behave/features/step.execute_steps.feature +59 -0
  227. data/vendor/behave/features/step.execute_steps.with_table.feature +65 -0
  228. data/vendor/behave/features/step.import_other_step_module.feature +103 -0
  229. data/vendor/behave/features/step.pending_steps.feature +128 -0
  230. data/vendor/behave/features/step.undefined_steps.feature +307 -0
  231. data/vendor/behave/features/step.use_step_library.feature +44 -0
  232. data/vendor/behave/features/step_dialect.generic_steps.feature +189 -0
  233. data/vendor/behave/features/step_dialect.given_when_then.feature +89 -0
  234. data/vendor/behave/features/step_param.builtin_types.with_float.feature +239 -0
  235. data/vendor/behave/features/step_param.builtin_types.with_integer.feature +305 -0
  236. data/vendor/behave/features/step_param.custom_types.feature +134 -0
  237. data/vendor/behave/features/steps/behave_active_tags_steps.py +86 -0
  238. data/vendor/behave/features/steps/behave_context_steps.py +67 -0
  239. data/vendor/behave/features/steps/behave_model_tag_logic_steps.py +105 -0
  240. data/vendor/behave/features/steps/behave_model_util.py +105 -0
  241. data/vendor/behave/features/steps/behave_select_files_steps.py +83 -0
  242. data/vendor/behave/features/steps/behave_tag_expression_steps.py +166 -0
  243. data/vendor/behave/features/steps/behave_undefined_steps.py +101 -0
  244. data/vendor/behave/features/steps/use_steplib_behave4cmd.py +12 -0
  245. data/vendor/behave/features/summary.undefined_steps.feature +114 -0
  246. data/vendor/behave/features/tags.active_tags.feature +385 -0
  247. data/vendor/behave/features/tags.default_tags.feature +104 -0
  248. data/vendor/behave/features/tags.tag_expression.feature +105 -0
  249. data/vendor/behave/features/userdata.feature +331 -0
  250. data/vendor/behave/invoke.yaml +21 -0
  251. data/vendor/behave/issue.features/README.txt +17 -0
  252. data/vendor/behave/issue.features/environment.py +97 -0
  253. data/vendor/behave/issue.features/issue0030.feature +21 -0
  254. data/vendor/behave/issue.features/issue0031.feature +16 -0
  255. data/vendor/behave/issue.features/issue0032.feature +28 -0
  256. data/vendor/behave/issue.features/issue0035.feature +74 -0
  257. data/vendor/behave/issue.features/issue0040.feature +154 -0
  258. data/vendor/behave/issue.features/issue0041.feature +135 -0
  259. data/vendor/behave/issue.features/issue0042.feature +230 -0
  260. data/vendor/behave/issue.features/issue0044.feature +51 -0
  261. data/vendor/behave/issue.features/issue0046.feature +77 -0
  262. data/vendor/behave/issue.features/issue0052.feature +66 -0
  263. data/vendor/behave/issue.features/issue0059.feature +29 -0
  264. data/vendor/behave/issue.features/issue0063.feature +102 -0
  265. data/vendor/behave/issue.features/issue0064.feature +97 -0
  266. data/vendor/behave/issue.features/issue0065.feature +18 -0
  267. data/vendor/behave/issue.features/issue0066.feature +80 -0
  268. data/vendor/behave/issue.features/issue0067.feature +90 -0
  269. data/vendor/behave/issue.features/issue0069.feature +64 -0
  270. data/vendor/behave/issue.features/issue0072.feature +32 -0
  271. data/vendor/behave/issue.features/issue0073.feature +228 -0
  272. data/vendor/behave/issue.features/issue0075.feature +18 -0
  273. data/vendor/behave/issue.features/issue0077.feature +89 -0
  274. data/vendor/behave/issue.features/issue0080.feature +49 -0
  275. data/vendor/behave/issue.features/issue0081.feature +138 -0
  276. data/vendor/behave/issue.features/issue0083.feature +69 -0
  277. data/vendor/behave/issue.features/issue0084.feature +69 -0
  278. data/vendor/behave/issue.features/issue0085.feature +119 -0
  279. data/vendor/behave/issue.features/issue0092.feature +66 -0
  280. data/vendor/behave/issue.features/issue0096.feature +173 -0
  281. data/vendor/behave/issue.features/issue0099.feature +130 -0
  282. data/vendor/behave/issue.features/issue0109.feature +60 -0
  283. data/vendor/behave/issue.features/issue0111.feature +53 -0
  284. data/vendor/behave/issue.features/issue0112.feature +64 -0
  285. data/vendor/behave/issue.features/issue0114.feature +118 -0
  286. data/vendor/behave/issue.features/issue0116.feature +71 -0
  287. data/vendor/behave/issue.features/issue0125.feature +49 -0
  288. data/vendor/behave/issue.features/issue0127.feature +64 -0
  289. data/vendor/behave/issue.features/issue0139.feature +67 -0
  290. data/vendor/behave/issue.features/issue0142.feature +37 -0
  291. data/vendor/behave/issue.features/issue0143.feature +54 -0
  292. data/vendor/behave/issue.features/issue0145.feature +63 -0
  293. data/vendor/behave/issue.features/issue0148.feature +105 -0
  294. data/vendor/behave/issue.features/issue0152.feature +52 -0
  295. data/vendor/behave/issue.features/issue0159.feature +74 -0
  296. data/vendor/behave/issue.features/issue0162.feature +86 -0
  297. data/vendor/behave/issue.features/issue0171.feature +16 -0
  298. data/vendor/behave/issue.features/issue0172.feature +51 -0
  299. data/vendor/behave/issue.features/issue0175.feature +91 -0
  300. data/vendor/behave/issue.features/issue0177.feature +40 -0
  301. data/vendor/behave/issue.features/issue0181.feature +36 -0
  302. data/vendor/behave/issue.features/issue0184.feature +144 -0
  303. data/vendor/behave/issue.features/issue0186.feature +12 -0
  304. data/vendor/behave/issue.features/issue0188.feature +60 -0
  305. data/vendor/behave/issue.features/issue0191.feature +178 -0
  306. data/vendor/behave/issue.features/issue0194.feature +215 -0
  307. data/vendor/behave/issue.features/issue0197.feature +11 -0
  308. data/vendor/behave/issue.features/issue0216.feature +129 -0
  309. data/vendor/behave/issue.features/issue0226.feature +51 -0
  310. data/vendor/behave/issue.features/issue0228.feature +41 -0
  311. data/vendor/behave/issue.features/issue0230.feature +46 -0
  312. data/vendor/behave/issue.features/issue0231.feature +77 -0
  313. data/vendor/behave/issue.features/issue0238.feature +52 -0
  314. data/vendor/behave/issue.features/issue0251.feature +15 -0
  315. data/vendor/behave/issue.features/issue0280.feature +118 -0
  316. data/vendor/behave/issue.features/issue0288.feature +95 -0
  317. data/vendor/behave/issue.features/issue0300.feature +49 -0
  318. data/vendor/behave/issue.features/issue0302.feature +91 -0
  319. data/vendor/behave/issue.features/issue0309.feature +52 -0
  320. data/vendor/behave/issue.features/issue0330.feature +124 -0
  321. data/vendor/behave/issue.features/issue0349.feature +9 -0
  322. data/vendor/behave/issue.features/issue0361.feature +79 -0
  323. data/vendor/behave/issue.features/issue0383.feature +76 -0
  324. data/vendor/behave/issue.features/issue0384.feature +103 -0
  325. data/vendor/behave/issue.features/issue0385.feature +109 -0
  326. data/vendor/behave/issue.features/issue0424.feature +66 -0
  327. data/vendor/behave/issue.features/issue0446.feature +116 -0
  328. data/vendor/behave/issue.features/issue0449.feature +42 -0
  329. data/vendor/behave/issue.features/issue0453.feature +42 -0
  330. data/vendor/behave/issue.features/issue0457.feature +65 -0
  331. data/vendor/behave/issue.features/issue0462.feature +38 -0
  332. data/vendor/behave/issue.features/issue0476.feature +39 -0
  333. data/vendor/behave/issue.features/issue0487.feature +92 -0
  334. data/vendor/behave/issue.features/issue0506.feature +77 -0
  335. data/vendor/behave/issue.features/issue0510.feature +51 -0
  336. data/vendor/behave/issue.features/requirements.txt +12 -0
  337. data/vendor/behave/issue.features/steps/ansi_steps.py +20 -0
  338. data/vendor/behave/issue.features/steps/behave_hooks_steps.py +10 -0
  339. data/vendor/behave/issue.features/steps/use_steplib_behave4cmd.py +13 -0
  340. data/vendor/behave/more.features/formatter.json.validate_output.feature +37 -0
  341. data/vendor/behave/more.features/steps/tutorial_steps.py +16 -0
  342. data/vendor/behave/more.features/steps/use_steplib_behave4cmd.py +7 -0
  343. data/vendor/behave/more.features/tutorial.feature +6 -0
  344. data/vendor/behave/py.requirements/README.txt +5 -0
  345. data/vendor/behave/py.requirements/all.txt +16 -0
  346. data/vendor/behave/py.requirements/basic.txt +21 -0
  347. data/vendor/behave/py.requirements/develop.txt +28 -0
  348. data/vendor/behave/py.requirements/docs.txt +6 -0
  349. data/vendor/behave/py.requirements/json.txt +7 -0
  350. data/vendor/behave/py.requirements/more_py26.txt +8 -0
  351. data/vendor/behave/py.requirements/testing.txt +10 -0
  352. data/vendor/behave/pytest.ini +24 -0
  353. data/vendor/behave/setup.cfg +29 -0
  354. data/vendor/behave/setup.py +118 -0
  355. data/vendor/behave/setuptools_behave.py +130 -0
  356. data/vendor/behave/tasks/__behave.py +45 -0
  357. data/vendor/behave/tasks/__init__.py +55 -0
  358. data/vendor/behave/tasks/__main__.py +70 -0
  359. data/vendor/behave/tasks/_setup.py +135 -0
  360. data/vendor/behave/tasks/_vendor/README.rst +35 -0
  361. data/vendor/behave/tasks/_vendor/invoke.zip +0 -0
  362. data/vendor/behave/tasks/_vendor/path.py +1725 -0
  363. data/vendor/behave/tasks/_vendor/pathlib.py +1280 -0
  364. data/vendor/behave/tasks/_vendor/six.py +868 -0
  365. data/vendor/behave/tasks/clean.py +246 -0
  366. data/vendor/behave/tasks/docs.py +97 -0
  367. data/vendor/behave/tasks/requirements.txt +17 -0
  368. data/vendor/behave/tasks/test.py +192 -0
  369. data/vendor/behave/test/__init__.py +0 -0
  370. data/vendor/behave/test/_importer_candidate.py +3 -0
  371. data/vendor/behave/test/reporters/__init__.py +0 -0
  372. data/vendor/behave/test/reporters/test_summary.py +240 -0
  373. data/vendor/behave/test/test_ansi_escapes.py +73 -0
  374. data/vendor/behave/test/test_configuration.py +172 -0
  375. data/vendor/behave/test/test_formatter.py +265 -0
  376. data/vendor/behave/test/test_formatter_progress.py +39 -0
  377. data/vendor/behave/test/test_formatter_rerun.py +97 -0
  378. data/vendor/behave/test/test_formatter_tags.py +57 -0
  379. data/vendor/behave/test/test_importer.py +151 -0
  380. data/vendor/behave/test/test_log_capture.py +29 -0
  381. data/vendor/behave/test/test_matchers.py +236 -0
  382. data/vendor/behave/test/test_model.py +871 -0
  383. data/vendor/behave/test/test_parser.py +1590 -0
  384. data/vendor/behave/test/test_runner.py +1074 -0
  385. data/vendor/behave/test/test_step_registry.py +96 -0
  386. data/vendor/behave/test/test_tag_expression.py +506 -0
  387. data/vendor/behave/test/test_tag_expression2.py +462 -0
  388. data/vendor/behave/test/test_tag_matcher.py +729 -0
  389. data/vendor/behave/test/test_userdata.py +184 -0
  390. data/vendor/behave/tests/README.txt +12 -0
  391. data/vendor/behave/tests/__init__.py +0 -0
  392. data/vendor/behave/tests/api/__ONLY_PY34_or_newer.txt +0 -0
  393. data/vendor/behave/tests/api/__init__.py +0 -0
  394. data/vendor/behave/tests/api/_test_async_step34.py +130 -0
  395. data/vendor/behave/tests/api/_test_async_step35.py +75 -0
  396. data/vendor/behave/tests/api/test_async_step.py +18 -0
  397. data/vendor/behave/tests/api/testing_support.py +94 -0
  398. data/vendor/behave/tests/api/testing_support_async.py +21 -0
  399. data/vendor/behave/tests/issues/test_issue0336.py +66 -0
  400. data/vendor/behave/tests/issues/test_issue0449.py +55 -0
  401. data/vendor/behave/tests/issues/test_issue0453.py +62 -0
  402. data/vendor/behave/tests/issues/test_issue0458.py +54 -0
  403. data/vendor/behave/tests/issues/test_issue0495.py +65 -0
  404. data/vendor/behave/tests/unit/__init__.py +0 -0
  405. data/vendor/behave/tests/unit/test_behave4cmd_command_shell_proc.py +135 -0
  406. data/vendor/behave/tests/unit/test_capture.py +280 -0
  407. data/vendor/behave/tests/unit/test_model_core.py +56 -0
  408. data/vendor/behave/tests/unit/test_textutil.py +267 -0
  409. data/vendor/behave/tools/test-features/background.feature +9 -0
  410. data/vendor/behave/tools/test-features/environment.py +8 -0
  411. data/vendor/behave/tools/test-features/french.feature +11 -0
  412. data/vendor/behave/tools/test-features/outline.feature +39 -0
  413. data/vendor/behave/tools/test-features/parse.feature +10 -0
  414. data/vendor/behave/tools/test-features/step-data.feature +60 -0
  415. data/vendor/behave/tools/test-features/steps/steps.py +120 -0
  416. data/vendor/behave/tools/test-features/tags.feature +18 -0
  417. data/vendor/behave/tox.ini +159 -0
  418. metadata +562 -0
@@ -0,0 +1,1280 @@
1
+ import fnmatch
2
+ import functools
3
+ import io
4
+ import ntpath
5
+ import os
6
+ import posixpath
7
+ import re
8
+ import sys
9
+ import time
10
+ from collections import Sequence
11
+ from contextlib import contextmanager
12
+ from errno import EINVAL, ENOENT
13
+ from operator import attrgetter
14
+ from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
15
+ try:
16
+ from urllib import quote as urlquote, quote as urlquote_from_bytes
17
+ except ImportError:
18
+ from urllib.parse import quote as urlquote, quote_from_bytes as urlquote_from_bytes
19
+
20
+
21
+ try:
22
+ intern = intern
23
+ except NameError:
24
+ intern = sys.intern
25
+ try:
26
+ basestring = basestring
27
+ except NameError:
28
+ basestring = str
29
+
30
+ supports_symlinks = True
31
+ try:
32
+ import nt
33
+ except ImportError:
34
+ nt = None
35
+ else:
36
+ if sys.getwindowsversion()[:2] >= (6, 0) and sys.version_info >= (3, 2):
37
+ from nt import _getfinalpathname
38
+ else:
39
+ supports_symlinks = False
40
+ _getfinalpathname = None
41
+
42
+
43
+ __all__ = [
44
+ "PurePath", "PurePosixPath", "PureWindowsPath",
45
+ "Path", "PosixPath", "WindowsPath",
46
+ ]
47
+
48
+ #
49
+ # Internals
50
+ #
51
+
52
+ _py2 = sys.version_info < (3,)
53
+ _py2_fs_encoding = 'ascii'
54
+
55
+ def _py2_fsencode(parts):
56
+ # py2 => minimal unicode support
57
+ return [part.encode(_py2_fs_encoding) if isinstance(part, unicode)
58
+ else part for part in parts]
59
+
60
+ def _is_wildcard_pattern(pat):
61
+ # Whether this pattern needs actual matching using fnmatch, or can
62
+ # be looked up directly as a file.
63
+ return "*" in pat or "?" in pat or "[" in pat
64
+
65
+
66
+ class _Flavour(object):
67
+ """A flavour implements a particular (platform-specific) set of path
68
+ semantics."""
69
+
70
+ def __init__(self):
71
+ self.join = self.sep.join
72
+
73
+ def parse_parts(self, parts):
74
+ if _py2:
75
+ parts = _py2_fsencode(parts)
76
+ parsed = []
77
+ sep = self.sep
78
+ altsep = self.altsep
79
+ drv = root = ''
80
+ it = reversed(parts)
81
+ for part in it:
82
+ if not part:
83
+ continue
84
+ if altsep:
85
+ part = part.replace(altsep, sep)
86
+ drv, root, rel = self.splitroot(part)
87
+ if sep in rel:
88
+ for x in reversed(rel.split(sep)):
89
+ if x and x != '.':
90
+ parsed.append(intern(x))
91
+ else:
92
+ if rel and rel != '.':
93
+ parsed.append(intern(rel))
94
+ if drv or root:
95
+ if not drv:
96
+ # If no drive is present, try to find one in the previous
97
+ # parts. This makes the result of parsing e.g.
98
+ # ("C:", "/", "a") reasonably intuitive.
99
+ for part in it:
100
+ drv = self.splitroot(part)[0]
101
+ if drv:
102
+ break
103
+ break
104
+ if drv or root:
105
+ parsed.append(drv + root)
106
+ parsed.reverse()
107
+ return drv, root, parsed
108
+
109
+ def join_parsed_parts(self, drv, root, parts, drv2, root2, parts2):
110
+ """
111
+ Join the two paths represented by the respective
112
+ (drive, root, parts) tuples. Return a new (drive, root, parts) tuple.
113
+ """
114
+ if root2:
115
+ if not drv2 and drv:
116
+ return drv, root2, [drv + root2] + parts2[1:]
117
+ elif drv2:
118
+ if drv2 == drv or self.casefold(drv2) == self.casefold(drv):
119
+ # Same drive => second path is relative to the first
120
+ return drv, root, parts + parts2[1:]
121
+ else:
122
+ # Second path is non-anchored (common case)
123
+ return drv, root, parts + parts2
124
+ return drv2, root2, parts2
125
+
126
+
127
+ class _WindowsFlavour(_Flavour):
128
+ # Reference for Windows paths can be found at
129
+ # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
130
+
131
+ sep = '\\'
132
+ altsep = '/'
133
+ has_drv = True
134
+ pathmod = ntpath
135
+
136
+ is_supported = (nt is not None)
137
+
138
+ drive_letters = (
139
+ set(chr(x) for x in range(ord('a'), ord('z') + 1)) |
140
+ set(chr(x) for x in range(ord('A'), ord('Z') + 1))
141
+ )
142
+ ext_namespace_prefix = '\\\\?\\'
143
+
144
+ reserved_names = (
145
+ set(['CON', 'PRN', 'AUX', 'NUL']) |
146
+ set(['COM%d' % i for i in range(1, 10)]) |
147
+ set(['LPT%d' % i for i in range(1, 10)])
148
+ )
149
+
150
+ # Interesting findings about extended paths:
151
+ # - '\\?\c:\a', '//?/c:\a' and '//?/c:/a' are all supported
152
+ # but '\\?\c:/a' is not
153
+ # - extended paths are always absolute; "relative" extended paths will
154
+ # fail.
155
+
156
+ def splitroot(self, part, sep=sep):
157
+ first = part[0:1]
158
+ second = part[1:2]
159
+ if (second == sep and first == sep):
160
+ # XXX extended paths should also disable the collapsing of "."
161
+ # components (according to MSDN docs).
162
+ prefix, part = self._split_extended_path(part)
163
+ first = part[0:1]
164
+ second = part[1:2]
165
+ else:
166
+ prefix = ''
167
+ third = part[2:3]
168
+ if (second == sep and first == sep and third != sep):
169
+ # is a UNC path:
170
+ # vvvvvvvvvvvvvvvvvvvvv root
171
+ # \\machine\mountpoint\directory\etc\...
172
+ # directory ^^^^^^^^^^^^^^
173
+ index = part.find(sep, 2)
174
+ if index != -1:
175
+ index2 = part.find(sep, index + 1)
176
+ # a UNC path can't have two slashes in a row
177
+ # (after the initial two)
178
+ if index2 != index + 1:
179
+ if index2 == -1:
180
+ index2 = len(part)
181
+ if prefix:
182
+ return prefix + part[1:index2], sep, part[index2+1:]
183
+ else:
184
+ return part[:index2], sep, part[index2+1:]
185
+ drv = root = ''
186
+ if second == ':' and first in self.drive_letters:
187
+ drv = part[:2]
188
+ part = part[2:]
189
+ first = third
190
+ if first == sep:
191
+ root = first
192
+ part = part.lstrip(sep)
193
+ return prefix + drv, root, part
194
+
195
+ def casefold(self, s):
196
+ return s.lower()
197
+
198
+ def casefold_parts(self, parts):
199
+ return [p.lower() for p in parts]
200
+
201
+ def resolve(self, path):
202
+ s = str(path)
203
+ if not s:
204
+ return os.getcwd()
205
+ if _getfinalpathname is not None:
206
+ return self._ext_to_normal(_getfinalpathname(s))
207
+ # Means fallback on absolute
208
+ return None
209
+
210
+ def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix):
211
+ prefix = ''
212
+ if s.startswith(ext_prefix):
213
+ prefix = s[:4]
214
+ s = s[4:]
215
+ if s.startswith('UNC\\'):
216
+ prefix += s[:3]
217
+ s = '\\' + s[3:]
218
+ return prefix, s
219
+
220
+ def _ext_to_normal(self, s):
221
+ # Turn back an extended path into a normal DOS-like path
222
+ return self._split_extended_path(s)[1]
223
+
224
+ def is_reserved(self, parts):
225
+ # NOTE: the rules for reserved names seem somewhat complicated
226
+ # (e.g. r"..\NUL" is reserved but not r"foo\NUL").
227
+ # We err on the side of caution and return True for paths which are
228
+ # not considered reserved by Windows.
229
+ if not parts:
230
+ return False
231
+ if parts[0].startswith('\\\\'):
232
+ # UNC paths are never reserved
233
+ return False
234
+ return parts[-1].partition('.')[0].upper() in self.reserved_names
235
+
236
+ def make_uri(self, path):
237
+ # Under Windows, file URIs use the UTF-8 encoding.
238
+ drive = path.drive
239
+ if len(drive) == 2 and drive[1] == ':':
240
+ # It's a path on a local drive => 'file:///c:/a/b'
241
+ rest = path.as_posix()[2:].lstrip('/')
242
+ return 'file:///%s/%s' % (
243
+ drive, urlquote_from_bytes(rest.encode('utf-8')))
244
+ else:
245
+ # It's a path on a network drive => 'file://host/share/a/b'
246
+ return 'file:' + urlquote_from_bytes(path.as_posix().encode('utf-8'))
247
+
248
+
249
+ class _PosixFlavour(_Flavour):
250
+ sep = '/'
251
+ altsep = ''
252
+ has_drv = False
253
+ pathmod = posixpath
254
+
255
+ is_supported = (os.name != 'nt')
256
+
257
+ def splitroot(self, part, sep=sep):
258
+ if part and part[0] == sep:
259
+ stripped_part = part.lstrip(sep)
260
+ # According to POSIX path resolution:
261
+ # http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11
262
+ # "A pathname that begins with two successive slashes may be
263
+ # interpreted in an implementation-defined manner, although more
264
+ # than two leading slashes shall be treated as a single slash".
265
+ if len(part) - len(stripped_part) == 2:
266
+ return '', sep * 2, stripped_part
267
+ else:
268
+ return '', sep, stripped_part
269
+ else:
270
+ return '', '', part
271
+
272
+ def casefold(self, s):
273
+ return s
274
+
275
+ def casefold_parts(self, parts):
276
+ return parts
277
+
278
+ def resolve(self, path):
279
+ sep = self.sep
280
+ accessor = path._accessor
281
+ seen = {}
282
+ def _resolve(path, rest):
283
+ if rest.startswith(sep):
284
+ path = ''
285
+
286
+ for name in rest.split(sep):
287
+ if not name or name == '.':
288
+ # current dir
289
+ continue
290
+ if name == '..':
291
+ # parent dir
292
+ path, _, _ = path.rpartition(sep)
293
+ continue
294
+ newpath = path + sep + name
295
+ if newpath in seen:
296
+ # Already seen this path
297
+ path = seen[newpath]
298
+ if path is not None:
299
+ # use cached value
300
+ continue
301
+ # The symlink is not resolved, so we must have a symlink loop.
302
+ raise RuntimeError("Symlink loop from %r" % newpath)
303
+ # Resolve the symbolic link
304
+ try:
305
+ target = accessor.readlink(newpath)
306
+ except OSError as e:
307
+ if e.errno != EINVAL:
308
+ raise
309
+ # Not a symlink
310
+ path = newpath
311
+ else:
312
+ seen[newpath] = None # not resolved symlink
313
+ path = _resolve(path, target)
314
+ seen[newpath] = path # resolved symlink
315
+
316
+ return path
317
+ # NOTE: according to POSIX, getcwd() cannot contain path components
318
+ # which are symlinks.
319
+ base = '' if path.is_absolute() else os.getcwd()
320
+ return _resolve(base, str(path)) or sep
321
+
322
+ def is_reserved(self, parts):
323
+ return False
324
+
325
+ def make_uri(self, path):
326
+ # We represent the path using the local filesystem encoding,
327
+ # for portability to other applications.
328
+ bpath = bytes(path)
329
+ return 'file://' + urlquote_from_bytes(bpath)
330
+
331
+
332
+ _windows_flavour = _WindowsFlavour()
333
+ _posix_flavour = _PosixFlavour()
334
+
335
+
336
+ class _Accessor:
337
+ """An accessor implements a particular (system-specific or not) way of
338
+ accessing paths on the filesystem."""
339
+
340
+
341
+ class _NormalAccessor(_Accessor):
342
+
343
+ def _wrap_strfunc(strfunc):
344
+ @functools.wraps(strfunc)
345
+ def wrapped(pathobj, *args):
346
+ return strfunc(str(pathobj), *args)
347
+ return staticmethod(wrapped)
348
+
349
+ def _wrap_binary_strfunc(strfunc):
350
+ @functools.wraps(strfunc)
351
+ def wrapped(pathobjA, pathobjB, *args):
352
+ return strfunc(str(pathobjA), str(pathobjB), *args)
353
+ return staticmethod(wrapped)
354
+
355
+ stat = _wrap_strfunc(os.stat)
356
+
357
+ lstat = _wrap_strfunc(os.lstat)
358
+
359
+ open = _wrap_strfunc(os.open)
360
+
361
+ listdir = _wrap_strfunc(os.listdir)
362
+
363
+ chmod = _wrap_strfunc(os.chmod)
364
+
365
+ if hasattr(os, "lchmod"):
366
+ lchmod = _wrap_strfunc(os.lchmod)
367
+ else:
368
+ def lchmod(self, pathobj, mode):
369
+ raise NotImplementedError("lchmod() not available on this system")
370
+
371
+ mkdir = _wrap_strfunc(os.mkdir)
372
+
373
+ unlink = _wrap_strfunc(os.unlink)
374
+
375
+ rmdir = _wrap_strfunc(os.rmdir)
376
+
377
+ rename = _wrap_binary_strfunc(os.rename)
378
+
379
+ if sys.version_info >= (3, 3):
380
+ replace = _wrap_binary_strfunc(os.replace)
381
+
382
+ if nt:
383
+ if supports_symlinks:
384
+ symlink = _wrap_binary_strfunc(os.symlink)
385
+ else:
386
+ def symlink(a, b, target_is_directory):
387
+ raise NotImplementedError("symlink() not available on this system")
388
+ else:
389
+ # Under POSIX, os.symlink() takes two args
390
+ @staticmethod
391
+ def symlink(a, b, target_is_directory):
392
+ return os.symlink(str(a), str(b))
393
+
394
+ utime = _wrap_strfunc(os.utime)
395
+
396
+ # Helper for resolve()
397
+ def readlink(self, path):
398
+ return os.readlink(path)
399
+
400
+
401
+ _normal_accessor = _NormalAccessor()
402
+
403
+
404
+ #
405
+ # Globbing helpers
406
+ #
407
+
408
+ @contextmanager
409
+ def _cached(func):
410
+ try:
411
+ func.__cached__
412
+ yield func
413
+ except AttributeError:
414
+ cache = {}
415
+ def wrapper(*args):
416
+ try:
417
+ return cache[args]
418
+ except KeyError:
419
+ value = cache[args] = func(*args)
420
+ return value
421
+ wrapper.__cached__ = True
422
+ try:
423
+ yield wrapper
424
+ finally:
425
+ cache.clear()
426
+
427
+ def _make_selector(pattern_parts):
428
+ pat = pattern_parts[0]
429
+ child_parts = pattern_parts[1:]
430
+ if pat == '**':
431
+ cls = _RecursiveWildcardSelector
432
+ elif '**' in pat:
433
+ raise ValueError("Invalid pattern: '**' can only be an entire path component")
434
+ elif _is_wildcard_pattern(pat):
435
+ cls = _WildcardSelector
436
+ else:
437
+ cls = _PreciseSelector
438
+ return cls(pat, child_parts)
439
+
440
+ if hasattr(functools, "lru_cache"):
441
+ _make_selector = functools.lru_cache()(_make_selector)
442
+
443
+
444
+ class _Selector:
445
+ """A selector matches a specific glob pattern part against the children
446
+ of a given path."""
447
+
448
+ def __init__(self, child_parts):
449
+ self.child_parts = child_parts
450
+ if child_parts:
451
+ self.successor = _make_selector(child_parts)
452
+ else:
453
+ self.successor = _TerminatingSelector()
454
+
455
+ def select_from(self, parent_path):
456
+ """Iterate over all child paths of `parent_path` matched by this
457
+ selector. This can contain parent_path itself."""
458
+ path_cls = type(parent_path)
459
+ is_dir = path_cls.is_dir
460
+ exists = path_cls.exists
461
+ listdir = parent_path._accessor.listdir
462
+ return self._select_from(parent_path, is_dir, exists, listdir)
463
+
464
+
465
+ class _TerminatingSelector:
466
+
467
+ def _select_from(self, parent_path, is_dir, exists, listdir):
468
+ yield parent_path
469
+
470
+
471
+ class _PreciseSelector(_Selector):
472
+
473
+ def __init__(self, name, child_parts):
474
+ self.name = name
475
+ _Selector.__init__(self, child_parts)
476
+
477
+ def _select_from(self, parent_path, is_dir, exists, listdir):
478
+ if not is_dir(parent_path):
479
+ return
480
+ path = parent_path._make_child_relpath(self.name)
481
+ if exists(path):
482
+ for p in self.successor._select_from(path, is_dir, exists, listdir):
483
+ yield p
484
+
485
+
486
+ class _WildcardSelector(_Selector):
487
+
488
+ def __init__(self, pat, child_parts):
489
+ self.pat = re.compile(fnmatch.translate(pat))
490
+ _Selector.__init__(self, child_parts)
491
+
492
+ def _select_from(self, parent_path, is_dir, exists, listdir):
493
+ if not is_dir(parent_path):
494
+ return
495
+ cf = parent_path._flavour.casefold
496
+ for name in listdir(parent_path):
497
+ casefolded = cf(name)
498
+ if self.pat.match(casefolded):
499
+ path = parent_path._make_child_relpath(name)
500
+ for p in self.successor._select_from(path, is_dir, exists, listdir):
501
+ yield p
502
+
503
+
504
+ class _RecursiveWildcardSelector(_Selector):
505
+
506
+ def __init__(self, pat, child_parts):
507
+ _Selector.__init__(self, child_parts)
508
+
509
+ def _iterate_directories(self, parent_path, is_dir, listdir):
510
+ yield parent_path
511
+ for name in listdir(parent_path):
512
+ path = parent_path._make_child_relpath(name)
513
+ if is_dir(path):
514
+ for p in self._iterate_directories(path, is_dir, listdir):
515
+ yield p
516
+
517
+ def _select_from(self, parent_path, is_dir, exists, listdir):
518
+ if not is_dir(parent_path):
519
+ return
520
+ with _cached(listdir) as listdir:
521
+ yielded = set()
522
+ try:
523
+ successor_select = self.successor._select_from
524
+ for starting_point in self._iterate_directories(parent_path, is_dir, listdir):
525
+ for p in successor_select(starting_point, is_dir, exists, listdir):
526
+ if p not in yielded:
527
+ yield p
528
+ yielded.add(p)
529
+ finally:
530
+ yielded.clear()
531
+
532
+
533
+ #
534
+ # Public API
535
+ #
536
+
537
+ class _PathParents(Sequence):
538
+ """This object provides sequence-like access to the logical ancestors
539
+ of a path. Don't try to construct it yourself."""
540
+ __slots__ = ('_pathcls', '_drv', '_root', '_parts')
541
+
542
+ def __init__(self, path):
543
+ # We don't store the instance to avoid reference cycles
544
+ self._pathcls = type(path)
545
+ self._drv = path._drv
546
+ self._root = path._root
547
+ self._parts = path._parts
548
+
549
+ def __len__(self):
550
+ if self._drv or self._root:
551
+ return len(self._parts) - 1
552
+ else:
553
+ return len(self._parts)
554
+
555
+ def __getitem__(self, idx):
556
+ if idx < 0 or idx >= len(self):
557
+ raise IndexError(idx)
558
+ return self._pathcls._from_parsed_parts(self._drv, self._root,
559
+ self._parts[:-idx - 1])
560
+
561
+ def __repr__(self):
562
+ return "<{0}.parents>".format(self._pathcls.__name__)
563
+
564
+
565
+ class PurePath(object):
566
+ """PurePath represents a filesystem path and offers operations which
567
+ don't imply any actual filesystem I/O. Depending on your system,
568
+ instantiating a PurePath will return either a PurePosixPath or a
569
+ PureWindowsPath object. You can also instantiate either of these classes
570
+ directly, regardless of your system.
571
+ """
572
+ __slots__ = (
573
+ '_drv', '_root', '_parts',
574
+ '_str', '_hash', '_pparts', '_cached_cparts',
575
+ )
576
+
577
+ def __new__(cls, *args):
578
+ """Construct a PurePath from one or several strings and or existing
579
+ PurePath objects. The strings and path objects are combined so as
580
+ to yield a canonicalized path, which is incorporated into the
581
+ new PurePath object.
582
+ """
583
+ if cls is PurePath:
584
+ cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
585
+ return cls._from_parts(args)
586
+
587
+ def __reduce__(self):
588
+ # Using the parts tuple helps share interned path parts
589
+ # when pickling related paths.
590
+ return (self.__class__, tuple(self._parts))
591
+
592
+ @classmethod
593
+ def _parse_args(cls, args):
594
+ # This is useful when you don't want to create an instance, just
595
+ # canonicalize some constructor arguments.
596
+ parts = []
597
+ for a in args:
598
+ if isinstance(a, PurePath):
599
+ parts += a._parts
600
+ elif isinstance(a, basestring):
601
+ parts.append(a)
602
+ else:
603
+ raise TypeError(
604
+ "argument should be a path or str object, not %r"
605
+ % type(a))
606
+ return cls._flavour.parse_parts(parts)
607
+
608
+ @classmethod
609
+ def _from_parts(cls, args, init=True):
610
+ # We need to call _parse_args on the instance, so as to get the
611
+ # right flavour.
612
+ self = object.__new__(cls)
613
+ drv, root, parts = self._parse_args(args)
614
+ self._drv = drv
615
+ self._root = root
616
+ self._parts = parts
617
+ if init:
618
+ self._init()
619
+ return self
620
+
621
+ @classmethod
622
+ def _from_parsed_parts(cls, drv, root, parts, init=True):
623
+ self = object.__new__(cls)
624
+ self._drv = drv
625
+ self._root = root
626
+ self._parts = parts
627
+ if init:
628
+ self._init()
629
+ return self
630
+
631
+ @classmethod
632
+ def _format_parsed_parts(cls, drv, root, parts):
633
+ if drv or root:
634
+ return drv + root + cls._flavour.join(parts[1:])
635
+ else:
636
+ return cls._flavour.join(parts)
637
+
638
+ def _init(self):
639
+ # Overriden in concrete Path
640
+ pass
641
+
642
+ def _make_child(self, args):
643
+ drv, root, parts = self._parse_args(args)
644
+ drv, root, parts = self._flavour.join_parsed_parts(
645
+ self._drv, self._root, self._parts, drv, root, parts)
646
+ return self._from_parsed_parts(drv, root, parts)
647
+
648
+ def __str__(self):
649
+ """Return the string representation of the path, suitable for
650
+ passing to system calls."""
651
+ try:
652
+ return self._str
653
+ except AttributeError:
654
+ self._str = self._format_parsed_parts(self._drv, self._root,
655
+ self._parts) or '.'
656
+ return self._str
657
+
658
+ def as_posix(self):
659
+ """Return the string representation of the path with forward (/)
660
+ slashes."""
661
+ f = self._flavour
662
+ return str(self).replace(f.sep, '/')
663
+
664
+ def __bytes__(self):
665
+ """Return the bytes representation of the path. This is only
666
+ recommended to use under Unix."""
667
+ if sys.version_info < (3, 2):
668
+ raise NotImplementedError("needs Python 3.2 or later")
669
+ return os.fsencode(str(self))
670
+
671
+ def __repr__(self):
672
+ return "{0}({1!r})".format(self.__class__.__name__, self.as_posix())
673
+
674
+ def as_uri(self):
675
+ """Return the path as a 'file' URI."""
676
+ if not self.is_absolute():
677
+ raise ValueError("relative path can't be expressed as a file URI")
678
+ return self._flavour.make_uri(self)
679
+
680
+ @property
681
+ def _cparts(self):
682
+ # Cached casefolded parts, for hashing and comparison
683
+ try:
684
+ return self._cached_cparts
685
+ except AttributeError:
686
+ self._cached_cparts = self._flavour.casefold_parts(self._parts)
687
+ return self._cached_cparts
688
+
689
+ def __eq__(self, other):
690
+ if not isinstance(other, PurePath):
691
+ return NotImplemented
692
+ return self._cparts == other._cparts and self._flavour is other._flavour
693
+
694
+ def __ne__(self, other):
695
+ return not self == other
696
+
697
+ def __hash__(self):
698
+ try:
699
+ return self._hash
700
+ except AttributeError:
701
+ self._hash = hash(tuple(self._cparts))
702
+ return self._hash
703
+
704
+ def __lt__(self, other):
705
+ if not isinstance(other, PurePath) or self._flavour is not other._flavour:
706
+ return NotImplemented
707
+ return self._cparts < other._cparts
708
+
709
+ def __le__(self, other):
710
+ if not isinstance(other, PurePath) or self._flavour is not other._flavour:
711
+ return NotImplemented
712
+ return self._cparts <= other._cparts
713
+
714
+ def __gt__(self, other):
715
+ if not isinstance(other, PurePath) or self._flavour is not other._flavour:
716
+ return NotImplemented
717
+ return self._cparts > other._cparts
718
+
719
+ def __ge__(self, other):
720
+ if not isinstance(other, PurePath) or self._flavour is not other._flavour:
721
+ return NotImplemented
722
+ return self._cparts >= other._cparts
723
+
724
+ drive = property(attrgetter('_drv'),
725
+ doc="""The drive prefix (letter or UNC path), if any.""")
726
+
727
+ root = property(attrgetter('_root'),
728
+ doc="""The root of the path, if any.""")
729
+
730
+ @property
731
+ def anchor(self):
732
+ """The concatenation of the drive and root, or ''."""
733
+ anchor = self._drv + self._root
734
+ return anchor
735
+
736
+ @property
737
+ def name(self):
738
+ """The final path component, if any."""
739
+ parts = self._parts
740
+ if len(parts) == (1 if (self._drv or self._root) else 0):
741
+ return ''
742
+ return parts[-1]
743
+
744
+ @property
745
+ def suffix(self):
746
+ """The final component's last suffix, if any."""
747
+ name = self.name
748
+ i = name.rfind('.')
749
+ if 0 < i < len(name) - 1:
750
+ return name[i:]
751
+ else:
752
+ return ''
753
+
754
+ @property
755
+ def suffixes(self):
756
+ """A list of the final component's suffixes, if any."""
757
+ name = self.name
758
+ if name.endswith('.'):
759
+ return []
760
+ name = name.lstrip('.')
761
+ return ['.' + suffix for suffix in name.split('.')[1:]]
762
+
763
+ @property
764
+ def stem(self):
765
+ """The final path component, minus its last suffix."""
766
+ name = self.name
767
+ i = name.rfind('.')
768
+ if 0 < i < len(name) - 1:
769
+ return name[:i]
770
+ else:
771
+ return name
772
+
773
+ def with_name(self, name):
774
+ """Return a new path with the file name changed."""
775
+ if not self.name:
776
+ raise ValueError("%r has an empty name" % (self,))
777
+ return self._from_parsed_parts(self._drv, self._root,
778
+ self._parts[:-1] + [name])
779
+
780
+ def with_suffix(self, suffix):
781
+ """Return a new path with the file suffix changed (or added, if none)."""
782
+ # XXX if suffix is None, should the current suffix be removed?
783
+ drv, root, parts = self._flavour.parse_parts((suffix,))
784
+ if drv or root or len(parts) != 1:
785
+ raise ValueError("Invalid suffix %r" % (suffix))
786
+ suffix = parts[0]
787
+ if not suffix.startswith('.'):
788
+ raise ValueError("Invalid suffix %r" % (suffix))
789
+ name = self.name
790
+ if not name:
791
+ raise ValueError("%r has an empty name" % (self,))
792
+ old_suffix = self.suffix
793
+ if not old_suffix:
794
+ name = name + suffix
795
+ else:
796
+ name = name[:-len(old_suffix)] + suffix
797
+ return self._from_parsed_parts(self._drv, self._root,
798
+ self._parts[:-1] + [name])
799
+
800
+ def relative_to(self, *other):
801
+ """Return the relative path to another path identified by the passed
802
+ arguments. If the operation is not possible (because this is not
803
+ a subpath of the other path), raise ValueError.
804
+ """
805
+ # For the purpose of this method, drive and root are considered
806
+ # separate parts, i.e.:
807
+ # Path('c:/').relative_to('c:') gives Path('/')
808
+ # Path('c:/').relative_to('/') raise ValueError
809
+ if not other:
810
+ raise TypeError("need at least one argument")
811
+ parts = self._parts
812
+ drv = self._drv
813
+ root = self._root
814
+ if root:
815
+ abs_parts = [drv, root] + parts[1:]
816
+ else:
817
+ abs_parts = parts
818
+ to_drv, to_root, to_parts = self._parse_args(other)
819
+ if to_root:
820
+ to_abs_parts = [to_drv, to_root] + to_parts[1:]
821
+ else:
822
+ to_abs_parts = to_parts
823
+ n = len(to_abs_parts)
824
+ cf = self._flavour.casefold_parts
825
+ if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts):
826
+ formatted = self._format_parsed_parts(to_drv, to_root, to_parts)
827
+ raise ValueError("{!r} does not start with {!r}"
828
+ .format(str(self), str(formatted)))
829
+ return self._from_parsed_parts('', root if n == 1 else '',
830
+ abs_parts[n:])
831
+
832
+ @property
833
+ def parts(self):
834
+ """An object providing sequence-like access to the
835
+ components in the filesystem path."""
836
+ # We cache the tuple to avoid building a new one each time .parts
837
+ # is accessed. XXX is this necessary?
838
+ try:
839
+ return self._pparts
840
+ except AttributeError:
841
+ self._pparts = tuple(self._parts)
842
+ return self._pparts
843
+
844
+ def joinpath(self, *args):
845
+ """Combine this path with one or several arguments, and return a
846
+ new path representing either a subpath (if all arguments are relative
847
+ paths) or a totally different path (if one of the arguments is
848
+ anchored).
849
+ """
850
+ return self._make_child(args)
851
+
852
+ def __truediv__(self, key):
853
+ return self._make_child((key,))
854
+
855
+ def __rtruediv__(self, key):
856
+ return self._from_parts([key] + self._parts)
857
+
858
+ if sys.version_info < (3,):
859
+ __div__ = __truediv__
860
+ __rdiv__ = __rtruediv__
861
+
862
+ @property
863
+ def parent(self):
864
+ """The logical parent of the path."""
865
+ drv = self._drv
866
+ root = self._root
867
+ parts = self._parts
868
+ if len(parts) == 1 and (drv or root):
869
+ return self
870
+ return self._from_parsed_parts(drv, root, parts[:-1])
871
+
872
+ @property
873
+ def parents(self):
874
+ """A sequence of this path's logical parents."""
875
+ return _PathParents(self)
876
+
877
+ def is_absolute(self):
878
+ """True if the path is absolute (has both a root and, if applicable,
879
+ a drive)."""
880
+ if not self._root:
881
+ return False
882
+ return not self._flavour.has_drv or bool(self._drv)
883
+
884
+ def is_reserved(self):
885
+ """Return True if the path contains one of the special names reserved
886
+ by the system, if any."""
887
+ return self._flavour.is_reserved(self._parts)
888
+
889
+ def match(self, path_pattern):
890
+ """
891
+ Return True if this path matches the given pattern.
892
+ """
893
+ cf = self._flavour.casefold
894
+ path_pattern = cf(path_pattern)
895
+ drv, root, pat_parts = self._flavour.parse_parts((path_pattern,))
896
+ if not pat_parts:
897
+ raise ValueError("empty pattern")
898
+ if drv and drv != cf(self._drv):
899
+ return False
900
+ if root and root != cf(self._root):
901
+ return False
902
+ parts = self._cparts
903
+ if drv or root:
904
+ if len(pat_parts) != len(parts):
905
+ return False
906
+ pat_parts = pat_parts[1:]
907
+ elif len(pat_parts) > len(parts):
908
+ return False
909
+ for part, pat in zip(reversed(parts), reversed(pat_parts)):
910
+ if not fnmatch.fnmatchcase(part, pat):
911
+ return False
912
+ return True
913
+
914
+
915
+ class PurePosixPath(PurePath):
916
+ _flavour = _posix_flavour
917
+ __slots__ = ()
918
+
919
+
920
+ class PureWindowsPath(PurePath):
921
+ _flavour = _windows_flavour
922
+ __slots__ = ()
923
+
924
+
925
+ # Filesystem-accessing classes
926
+
927
+
928
+ class Path(PurePath):
929
+ __slots__ = (
930
+ '_accessor',
931
+ )
932
+
933
+ def __new__(cls, *args, **kwargs):
934
+ if cls is Path:
935
+ cls = WindowsPath if os.name == 'nt' else PosixPath
936
+ self = cls._from_parts(args, init=False)
937
+ if not self._flavour.is_supported:
938
+ raise NotImplementedError("cannot instantiate %r on your system"
939
+ % (cls.__name__,))
940
+ self._init()
941
+ return self
942
+
943
+ def _init(self,
944
+ # Private non-constructor arguments
945
+ template=None,
946
+ ):
947
+ if template is not None:
948
+ self._accessor = template._accessor
949
+ else:
950
+ self._accessor = _normal_accessor
951
+
952
+ def _make_child_relpath(self, part):
953
+ # This is an optimization used for dir walking. `part` must be
954
+ # a single part relative to this path.
955
+ parts = self._parts + [part]
956
+ return self._from_parsed_parts(self._drv, self._root, parts)
957
+
958
+ def _opener(self, name, flags, mode=0o666):
959
+ # A stub for the opener argument to built-in open()
960
+ return self._accessor.open(self, flags, mode)
961
+
962
+ def _raw_open(self, flags, mode=0o777):
963
+ """
964
+ Open the file pointed by this path and return a file descriptor,
965
+ as os.open() does.
966
+ """
967
+ return self._accessor.open(self, flags, mode)
968
+
969
+ # Public API
970
+
971
+ @classmethod
972
+ def cwd(cls):
973
+ """Return a new path pointing to the current working directory
974
+ (as returned by os.getcwd()).
975
+ """
976
+ return cls(os.getcwd())
977
+
978
+ def iterdir(self):
979
+ """Iterate over the files in this directory. Does not yield any
980
+ result for the special paths '.' and '..'.
981
+ """
982
+ for name in self._accessor.listdir(self):
983
+ if name in ('.', '..'):
984
+ # Yielding a path object for these makes little sense
985
+ continue
986
+ yield self._make_child_relpath(name)
987
+
988
+ def glob(self, pattern):
989
+ """Iterate over this subtree and yield all existing files (of any
990
+ kind, including directories) matching the given pattern.
991
+ """
992
+ pattern = self._flavour.casefold(pattern)
993
+ drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
994
+ if drv or root:
995
+ raise NotImplementedError("Non-relative patterns are unsupported")
996
+ selector = _make_selector(tuple(pattern_parts))
997
+ for p in selector.select_from(self):
998
+ yield p
999
+
1000
+ def rglob(self, pattern):
1001
+ """Recursively yield all existing files (of any kind, including
1002
+ directories) matching the given pattern, anywhere in this subtree.
1003
+ """
1004
+ pattern = self._flavour.casefold(pattern)
1005
+ drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
1006
+ if drv or root:
1007
+ raise NotImplementedError("Non-relative patterns are unsupported")
1008
+ selector = _make_selector(("**",) + tuple(pattern_parts))
1009
+ for p in selector.select_from(self):
1010
+ yield p
1011
+
1012
+ def absolute(self):
1013
+ """Return an absolute version of this path. This function works
1014
+ even if the path doesn't point to anything.
1015
+
1016
+ No normalization is done, i.e. all '.' and '..' will be kept along.
1017
+ Use resolve() to get the canonical path to a file.
1018
+ """
1019
+ # XXX untested yet!
1020
+ if self.is_absolute():
1021
+ return self
1022
+ # FIXME this must defer to the specific flavour (and, under Windows,
1023
+ # use nt._getfullpathname())
1024
+ obj = self._from_parts([os.getcwd()] + self._parts, init=False)
1025
+ obj._init(template=self)
1026
+ return obj
1027
+
1028
+ def resolve(self):
1029
+ """
1030
+ Make the path absolute, resolving all symlinks on the way and also
1031
+ normalizing it (for example turning slashes into backslashes under
1032
+ Windows).
1033
+ """
1034
+ s = self._flavour.resolve(self)
1035
+ if s is None:
1036
+ # No symlink resolution => for consistency, raise an error if
1037
+ # the path doesn't exist or is forbidden
1038
+ self.stat()
1039
+ s = str(self.absolute())
1040
+ # Now we have no symlinks in the path, it's safe to normalize it.
1041
+ normed = self._flavour.pathmod.normpath(s)
1042
+ obj = self._from_parts((normed,), init=False)
1043
+ obj._init(template=self)
1044
+ return obj
1045
+
1046
+ def stat(self):
1047
+ """
1048
+ Return the result of the stat() system call on this path, like
1049
+ os.stat() does.
1050
+ """
1051
+ return self._accessor.stat(self)
1052
+
1053
+ def owner(self):
1054
+ """
1055
+ Return the login name of the file owner.
1056
+ """
1057
+ import pwd
1058
+ return pwd.getpwuid(self.stat().st_uid).pw_name
1059
+
1060
+ def group(self):
1061
+ """
1062
+ Return the group name of the file gid.
1063
+ """
1064
+ import grp
1065
+ return grp.getgrgid(self.stat().st_gid).gr_name
1066
+
1067
+ def open(self, mode='r', buffering=-1, encoding=None,
1068
+ errors=None, newline=None):
1069
+ """
1070
+ Open the file pointed by this path and return a file object, as
1071
+ the built-in open() function does.
1072
+ """
1073
+ if sys.version_info >= (3, 3):
1074
+ return io.open(str(self), mode, buffering, encoding, errors, newline,
1075
+ opener=self._opener)
1076
+ else:
1077
+ return io.open(str(self), mode, buffering, encoding, errors, newline)
1078
+
1079
+ def touch(self, mode=0o666, exist_ok=True):
1080
+ """
1081
+ Create this file with the given access mode, if it doesn't exist.
1082
+ """
1083
+ if exist_ok:
1084
+ # First try to bump modification time
1085
+ # Implementation note: GNU touch uses the UTIME_NOW option of
1086
+ # the utimensat() / futimens() functions.
1087
+ t = time.time()
1088
+ try:
1089
+ self._accessor.utime(self, (t, t))
1090
+ except OSError:
1091
+ # Avoid exception chaining
1092
+ pass
1093
+ else:
1094
+ return
1095
+ flags = os.O_CREAT | os.O_WRONLY
1096
+ if not exist_ok:
1097
+ flags |= os.O_EXCL
1098
+ fd = self._raw_open(flags, mode)
1099
+ os.close(fd)
1100
+
1101
+ def mkdir(self, mode=0o777, parents=False):
1102
+ if not parents:
1103
+ self._accessor.mkdir(self, mode)
1104
+ else:
1105
+ try:
1106
+ self._accessor.mkdir(self, mode)
1107
+ except OSError as e:
1108
+ if e.errno != ENOENT:
1109
+ raise
1110
+ self.parent.mkdir(parents=True)
1111
+ self._accessor.mkdir(self, mode)
1112
+
1113
+ def chmod(self, mode):
1114
+ """
1115
+ Change the permissions of the path, like os.chmod().
1116
+ """
1117
+ self._accessor.chmod(self, mode)
1118
+
1119
+ def lchmod(self, mode):
1120
+ """
1121
+ Like chmod(), except if the path points to a symlink, the symlink's
1122
+ permissions are changed, rather than its target's.
1123
+ """
1124
+ self._accessor.lchmod(self, mode)
1125
+
1126
+ def unlink(self):
1127
+ """
1128
+ Remove this file or link.
1129
+ If the path is a directory, use rmdir() instead.
1130
+ """
1131
+ self._accessor.unlink(self)
1132
+
1133
+ def rmdir(self):
1134
+ """
1135
+ Remove this directory. The directory must be empty.
1136
+ """
1137
+ self._accessor.rmdir(self)
1138
+
1139
+ def lstat(self):
1140
+ """
1141
+ Like stat(), except if the path points to a symlink, the symlink's
1142
+ status information is returned, rather than its target's.
1143
+ """
1144
+ return self._accessor.lstat(self)
1145
+
1146
+ def rename(self, target):
1147
+ """
1148
+ Rename this path to the given path.
1149
+ """
1150
+ self._accessor.rename(self, target)
1151
+
1152
+ def replace(self, target):
1153
+ """
1154
+ Rename this path to the given path, clobbering the existing
1155
+ destination if it exists.
1156
+ """
1157
+ if sys.version_info < (3, 3):
1158
+ raise NotImplementedError("replace() is only available "
1159
+ "with Python 3.3 and later")
1160
+ self._accessor.replace(self, target)
1161
+
1162
+ def symlink_to(self, target, target_is_directory=False):
1163
+ """
1164
+ Make this path a symlink pointing to the given path.
1165
+ Note the order of arguments (self, target) is the reverse of os.symlink's.
1166
+ """
1167
+ self._accessor.symlink(target, self, target_is_directory)
1168
+
1169
+ # Convenience functions for querying the stat results
1170
+
1171
+ def exists(self):
1172
+ """
1173
+ Whether this path exists.
1174
+ """
1175
+ try:
1176
+ self.stat()
1177
+ except OSError as e:
1178
+ if e.errno != ENOENT:
1179
+ raise
1180
+ return False
1181
+ return True
1182
+
1183
+ def is_dir(self):
1184
+ """
1185
+ Whether this path is a directory.
1186
+ """
1187
+ try:
1188
+ return S_ISDIR(self.stat().st_mode)
1189
+ except OSError as e:
1190
+ if e.errno != ENOENT:
1191
+ raise
1192
+ # Path doesn't exist or is a broken symlink
1193
+ # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
1194
+ return False
1195
+
1196
+ def is_file(self):
1197
+ """
1198
+ Whether this path is a regular file (also True for symlinks pointing
1199
+ to regular files).
1200
+ """
1201
+ try:
1202
+ return S_ISREG(self.stat().st_mode)
1203
+ except OSError as e:
1204
+ if e.errno != ENOENT:
1205
+ raise
1206
+ # Path doesn't exist or is a broken symlink
1207
+ # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
1208
+ return False
1209
+
1210
+ def is_symlink(self):
1211
+ """
1212
+ Whether this path is a symbolic link.
1213
+ """
1214
+ try:
1215
+ return S_ISLNK(self.lstat().st_mode)
1216
+ except OSError as e:
1217
+ if e.errno != ENOENT:
1218
+ raise
1219
+ # Path doesn't exist
1220
+ return False
1221
+
1222
+ def is_block_device(self):
1223
+ """
1224
+ Whether this path is a block device.
1225
+ """
1226
+ try:
1227
+ return S_ISBLK(self.stat().st_mode)
1228
+ except OSError as e:
1229
+ if e.errno != ENOENT:
1230
+ raise
1231
+ # Path doesn't exist or is a broken symlink
1232
+ # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
1233
+ return False
1234
+
1235
+ def is_char_device(self):
1236
+ """
1237
+ Whether this path is a character device.
1238
+ """
1239
+ try:
1240
+ return S_ISCHR(self.stat().st_mode)
1241
+ except OSError as e:
1242
+ if e.errno != ENOENT:
1243
+ raise
1244
+ # Path doesn't exist or is a broken symlink
1245
+ # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
1246
+ return False
1247
+
1248
+ def is_fifo(self):
1249
+ """
1250
+ Whether this path is a FIFO.
1251
+ """
1252
+ try:
1253
+ return S_ISFIFO(self.stat().st_mode)
1254
+ except OSError as e:
1255
+ if e.errno != ENOENT:
1256
+ raise
1257
+ # Path doesn't exist or is a broken symlink
1258
+ # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
1259
+ return False
1260
+
1261
+ def is_socket(self):
1262
+ """
1263
+ Whether this path is a socket.
1264
+ """
1265
+ try:
1266
+ return S_ISSOCK(self.stat().st_mode)
1267
+ except OSError as e:
1268
+ if e.errno != ENOENT:
1269
+ raise
1270
+ # Path doesn't exist or is a broken symlink
1271
+ # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
1272
+ return False
1273
+
1274
+
1275
+ class PosixPath(Path, PurePosixPath):
1276
+ __slots__ = ()
1277
+
1278
+ class WindowsPath(Path, PureWindowsPath):
1279
+ __slots__ = ()
1280
+