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,615 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ from __future__ import absolute_import, with_statement
4
+ import re
5
+ import sys
6
+ import six
7
+ from behave import model, i18n
8
+ from behave.textutil import text as _text
9
+
10
+
11
+ DEFAULT_LANGUAGE = "en"
12
+
13
+
14
+ def parse_file(filename, language=None):
15
+ with open(filename, "rb") as f:
16
+ # file encoding is assumed to be utf8. Oh, yes.
17
+ data = f.read().decode("utf8")
18
+ return parse_feature(data, language, filename)
19
+
20
+
21
+ def parse_feature(data, language=None, filename=None):
22
+ # ALL data operated on by the parser MUST be unicode
23
+ assert isinstance(data, six.text_type)
24
+
25
+ try:
26
+ result = Parser(language).parse(data, filename)
27
+ except ParserError as e:
28
+ e.filename = filename
29
+ raise
30
+
31
+ return result
32
+
33
+ def parse_steps(text, language=None, filename=None):
34
+ """
35
+ Parse a number of steps a multi-line text from a scenario.
36
+ Scenario line with title and keyword is not provided.
37
+
38
+ :param text: Multi-line text with steps to parse (as unicode).
39
+ :param language: i18n language identifier (optional).
40
+ :param filename: Filename (optional).
41
+ :return: Parsed steps (if successful).
42
+ """
43
+ assert isinstance(text, six.text_type)
44
+ try:
45
+ result = Parser(language, variant="steps").parse_steps(text, filename)
46
+ except ParserError as e:
47
+ e.filename = filename
48
+ raise
49
+ return result
50
+
51
+ def parse_tags(text):
52
+ """
53
+ Parse tags from text (one or more lines, as string).
54
+
55
+ :param text: Multi-line text with tags to parse (as unicode).
56
+ :return: List of tags (if successful).
57
+ """
58
+ # assert isinstance(text, unicode)
59
+ if not text:
60
+ return []
61
+ return Parser(variant="tags").parse_tags(text)
62
+
63
+
64
+ class ParserError(Exception):
65
+ def __init__(self, message, line, filename=None, line_text=None):
66
+ if line:
67
+ message += u" at line %d" % line
68
+ if line_text:
69
+ message += u': "%s"' % line_text.strip()
70
+ super(ParserError, self).__init__(message)
71
+ self.line = line
72
+ self.line_text = line_text
73
+ self.filename = filename
74
+
75
+ def __str__(self):
76
+ arg0 = _text(self.args[0])
77
+ if self.filename:
78
+ filename = _text(self.filename, sys.getfilesystemencoding())
79
+ return u'Failed to parse "%s": %s' % (filename, arg0)
80
+ else:
81
+ return u"Failed to parse <string>: %s" % arg0
82
+
83
+ if six.PY2:
84
+ __unicode__ = __str__
85
+ __str__ = lambda self: self.__unicode__().encode("utf-8")
86
+
87
+
88
+ class Parser(object):
89
+ """Feature file parser for behave."""
90
+ # pylint: disable=too-many-instance-attributes
91
+
92
+ def __init__(self, language=None, variant=None):
93
+ if not variant:
94
+ variant = "feature"
95
+ self.language = language
96
+ self.variant = variant
97
+ self.state = "init"
98
+ self.line = 0
99
+ self.last_step = None
100
+ self.multiline_start = None
101
+ self.multiline_leading = None
102
+ self.multiline_terminator = None
103
+
104
+ self.filename = None
105
+ self.feature = None
106
+ self.statement = None
107
+ self.tags = []
108
+ self.lines = []
109
+ self.table = None
110
+ self.examples = None
111
+ self.keywords = None
112
+ if self.language:
113
+ self.keywords = i18n.languages[self.language]
114
+ # NOT-NEEDED: self.reset()
115
+
116
+ def reset(self):
117
+ # This can probably go away.
118
+ if self.language:
119
+ self.keywords = i18n.languages[self.language]
120
+ else:
121
+ self.keywords = None
122
+
123
+ self.state = "init"
124
+ self.line = 0
125
+ self.last_step = None
126
+ self.multiline_start = None
127
+ self.multiline_leading = None
128
+ self.multiline_terminator = None
129
+
130
+ self.filename = None
131
+ self.feature = None
132
+ self.statement = None
133
+ self.tags = []
134
+ self.lines = []
135
+ self.table = None
136
+ self.examples = None
137
+
138
+ def parse(self, data, filename=None):
139
+ self.reset()
140
+
141
+ self.filename = filename
142
+
143
+ for line in data.split("\n"):
144
+ self.line += 1
145
+ if not line.strip() and self.state != "multiline":
146
+ # -- SKIP EMPTY LINES, except in multiline string args.
147
+ continue
148
+ self.action(line)
149
+
150
+ if self.table:
151
+ self.action_table("")
152
+
153
+ feature = self.feature
154
+ if feature:
155
+ feature.parser = self
156
+ self.reset()
157
+ return feature
158
+
159
+ def _build_feature(self, keyword, line):
160
+ name = line[len(keyword) + 1:].strip()
161
+ language = self.language or DEFAULT_LANGUAGE
162
+ self.feature = model.Feature(self.filename, self.line, keyword,
163
+ name, tags=self.tags, language=language)
164
+ # -- RESET STATE:
165
+ self.tags = []
166
+
167
+ def _build_background_statement(self, keyword, line):
168
+ if self.tags:
169
+ msg = u"Background supports no tags: @%s" % (u" @".join(self.tags))
170
+ raise ParserError(msg, self.line, self.filename, line)
171
+ name = line[len(keyword) + 1:].strip()
172
+ statement = model.Background(self.filename, self.line, keyword, name)
173
+ self.statement = statement
174
+ self.feature.background = self.statement
175
+
176
+ def _build_scenario_statement(self, keyword, line):
177
+ name = line[len(keyword) + 1:].strip()
178
+ self.statement = model.Scenario(self.filename, self.line,
179
+ keyword, name, tags=self.tags)
180
+ self.feature.add_scenario(self.statement)
181
+ # -- RESET STATE:
182
+ self.tags = []
183
+
184
+ def _build_scenario_outline_statement(self, keyword, line):
185
+ # pylint: disable=C0103
186
+ # C0103 Invalid name "build_scenario_outline_statement", too long.
187
+ name = line[len(keyword) + 1:].strip()
188
+ self.statement = model.ScenarioOutline(self.filename, self.line,
189
+ keyword, name, tags=self.tags)
190
+ self.feature.add_scenario(self.statement)
191
+ # -- RESET STATE:
192
+ self.tags = []
193
+
194
+ def _build_examples(self, keyword, line):
195
+ if not isinstance(self.statement, model.ScenarioOutline):
196
+ message = u"Examples must only appear inside scenario outline"
197
+ raise ParserError(message, self.line, self.filename, line)
198
+ name = line[len(keyword) + 1:].strip()
199
+ self.examples = model.Examples(self.filename, self.line,
200
+ keyword, name, tags=self.tags)
201
+ # pylint: disable=E1103
202
+ # E1103 Instance of "Background" has no "examples" member
203
+ # (but some types could not be inferred).
204
+ self.statement.examples.append(self.examples)
205
+
206
+ # -- RESET STATE:
207
+ self.tags = []
208
+
209
+
210
+ def diagnose_feature_usage_error(self):
211
+ if self.feature:
212
+ return "Multiple features in one file are not supported."
213
+ else:
214
+ return "Feature should not be used here."
215
+
216
+ def diagnose_background_usage_error(self):
217
+ if self.feature and self.feature.scenarios:
218
+ return "Background may not occur after Scenario/ScenarioOutline."
219
+ elif self.tags:
220
+ return "Background does not support tags."
221
+ else:
222
+ return "Background should not be used here."
223
+
224
+ def diagnose_scenario_usage_error(self):
225
+ if not self.feature:
226
+ return "Scenario may not occur before Feature."
227
+ else:
228
+ return "Scenario should not be used here."
229
+
230
+ def diagnose_scenario_outline_usage_error(self): # pylint: disable=invalid-name
231
+ if not self.feature:
232
+ return "ScenarioOutline may not occur before Feature."
233
+ else:
234
+ return "ScenarioOutline should not be used here."
235
+
236
+ def ask_parse_failure_oracle(self, line):
237
+ """
238
+ Try to find the failure reason when a parse failure occurs:
239
+
240
+ Oracle, oracle, ... what went wrong?
241
+ Zzzz
242
+
243
+ :param line: Text line where parse failure occured (as string).
244
+ :return: Reason (as string) if an explanation is found.
245
+ Otherwise, empty string or None.
246
+ """
247
+ feature_kwd = self.match_keyword("feature", line)
248
+ if feature_kwd:
249
+ return self.diagnose_feature_usage_error()
250
+ background_kwd = self.match_keyword("background", line)
251
+ if background_kwd:
252
+ return self.diagnose_background_usage_error()
253
+ scenario_kwd = self.match_keyword("scenario", line)
254
+ if scenario_kwd:
255
+ return self.diagnose_scenario_usage_error()
256
+ scenario_outline_kwd = self.match_keyword("scenario_outline", line)
257
+ if scenario_outline_kwd:
258
+ return self.diagnose_scenario_outline_usage_error()
259
+ # -- OTHERWISE:
260
+ if self.variant == "feature" and not self.feature:
261
+ return "No feature found."
262
+ # -- FINALLY: No glue what went wrong.
263
+ return None
264
+
265
+ def action(self, line):
266
+ if line.strip().startswith("#") and self.state != "multiline":
267
+ if self.state != "init" or self.tags or self.variant != "feature":
268
+ return
269
+
270
+ # -- DETECT: language comment (at begin of feature file; state=init)
271
+ line = line.strip()[1:].strip()
272
+ if line.lstrip().lower().startswith("language:"):
273
+ language = line[9:].strip()
274
+ self.language = language
275
+ self.keywords = i18n.languages[language]
276
+ return
277
+
278
+ func = getattr(self, "action_" + self.state, None)
279
+ if func is None:
280
+ line = line.strip()
281
+ msg = u"Parser in unknown state %s;" % self.state
282
+ raise ParserError(msg, self.line, self.filename, line)
283
+ if not func(line):
284
+ line = line.strip()
285
+ msg = u'\nParser failure in state %s, at line %d: "%s"\n' % \
286
+ (self.state, self.line, line)
287
+ reason = self.ask_parse_failure_oracle(line)
288
+ if reason:
289
+ msg += u"REASON: %s" % reason
290
+ raise ParserError(msg, None, self.filename)
291
+
292
+ def action_init(self, line):
293
+ line = line.strip()
294
+ if line.startswith("@"):
295
+ self.tags.extend(self.parse_tags(line))
296
+ return True
297
+
298
+ feature_kwd = self.match_keyword("feature", line)
299
+ if feature_kwd:
300
+ self._build_feature(feature_kwd, line)
301
+ self.state = "feature"
302
+ return True
303
+ return False
304
+
305
+ # def subaction_detect_next_scenario(self, line):
306
+ # if line.startswith("@"):
307
+ # self.tags.extend(self.parse_tags(line))
308
+ # self.state = "next_scenario"
309
+ # return True
310
+ #
311
+ # scenario_kwd = self.match_keyword("scenario", line)
312
+ # if scenario_kwd:
313
+ # self._build_scenario_statement(scenario_kwd, line)
314
+ # self.state = "scenario"
315
+ # return True
316
+ #
317
+ # scenario_outline_kwd = self.match_keyword("scenario_outline", line)
318
+ # if scenario_outline_kwd:
319
+ # self._build_scenario_outline_statement(scenario_outline_kwd, line)
320
+ # self.state = "scenario"
321
+ # return True
322
+ #
323
+ # # -- OTHERWISE:
324
+ # return False
325
+
326
+ # pylint: disable=invalid-name
327
+ def subaction_detect_taggable_statement(self, line):
328
+ """Subaction is used after first tag line is detected.
329
+ Additional lines with tags or taggable_statement follow.
330
+
331
+ Taggable statements (excluding Feature) are:
332
+ * Scenario
333
+ * ScenarioOutline
334
+ * Examples (within ScenarioOutline)
335
+ """
336
+ if line.startswith("@"):
337
+ self.tags.extend(self.parse_tags(line))
338
+ self.state = "taggable_statement"
339
+ return True
340
+
341
+ scenario_kwd = self.match_keyword("scenario", line)
342
+ if scenario_kwd:
343
+ self._build_scenario_statement(scenario_kwd, line)
344
+ self.state = "scenario"
345
+ return True
346
+
347
+ scenario_outline_kwd = self.match_keyword("scenario_outline", line)
348
+ if scenario_outline_kwd:
349
+ self._build_scenario_outline_statement(scenario_outline_kwd, line)
350
+ self.state = "scenario"
351
+ return True
352
+
353
+ examples_kwd = self.match_keyword("examples", line)
354
+ if examples_kwd:
355
+ self._build_examples(examples_kwd, line)
356
+ self.state = "table"
357
+ return True
358
+
359
+ # -- OTHERWISE:
360
+ return False
361
+ # pylint: enable=invalid-name
362
+
363
+ def action_feature(self, line):
364
+ line = line.strip()
365
+ # OLD: if self.subaction_detect_next_scenario(line):
366
+ if self.subaction_detect_taggable_statement(line):
367
+ # -- DETECTED: Next Scenario, ScenarioOutline (or tags)
368
+ return True
369
+
370
+ background_kwd = self.match_keyword("background", line)
371
+ if background_kwd:
372
+ self._build_background_statement(background_kwd, line)
373
+ self.state = "steps"
374
+ return True
375
+
376
+ self.feature.description.append(line)
377
+ return True
378
+
379
+ # def action_next_scenario(self, line):
380
+ # """
381
+ # Entered after first tag for Scenario/ScenarioOutline is detected.
382
+ # """
383
+ # line = line.strip()
384
+ # if self.subaction_detect_next_scenario(line):
385
+ # return True
386
+ #
387
+ # return False
388
+
389
+ def action_taggable_statement(self, line):
390
+ """Entered after first tag for Scenario/ScenarioOutline or
391
+ Examples is detected (= taggable_statement except Feature).
392
+
393
+ Taggable statements (excluding Feature) are:
394
+ * Scenario
395
+ * ScenarioOutline
396
+ * Examples (within ScenarioOutline)
397
+ """
398
+ line = line.strip()
399
+ if self.subaction_detect_taggable_statement(line):
400
+ # -- DETECTED: Next Scenario, ScenarioOutline or Examples (or tags)
401
+ return True
402
+
403
+ return False
404
+
405
+ def action_scenario(self, line):
406
+ """
407
+ Entered when Scenario/ScenarioOutline keyword/line is detected.
408
+ Hunts/collects scenario description lines.
409
+
410
+ DETECT:
411
+ * first step of Scenario/ScenarioOutline
412
+ * next Scenario/ScenarioOutline.
413
+ """
414
+ line = line.strip()
415
+ step = self.parse_step(line)
416
+ if step:
417
+ # -- FIRST STEP DETECTED: End collection of scenario descriptions.
418
+ self.state = "steps"
419
+ self.statement.steps.append(step)
420
+ return True
421
+
422
+ # -- CASE: Detect next Scenario/ScenarioOutline
423
+ # * Scenario with scenario description, but without steps.
424
+ # * Title-only scenario without scenario description and steps.
425
+ # OLD: if self.subaction_detect_next_scenario(line):
426
+ if self.subaction_detect_taggable_statement(line):
427
+ # -- DETECTED: Next Scenario, ScenarioOutline (or tags)
428
+ return True
429
+
430
+ # -- OTHERWISE: Add scenario description line.
431
+ # pylint: disable=E1103
432
+ # E1103 Instance of "Background" has no "description" member...
433
+ self.statement.description.append(line)
434
+ return True
435
+
436
+ def action_steps(self, line):
437
+ """
438
+ Entered when first step is detected (or nested step parsing).
439
+
440
+ Subcases:
441
+ * step
442
+ * multi-line text (doc-string), following a step
443
+ * table, following a step
444
+ * examples for a ScenarioOutline, after ScenarioOutline steps
445
+
446
+ DETECT:
447
+ * next Scenario/ScenarioOutline or Examples (in a ScenarioOutline)
448
+ """
449
+ # pylint: disable=R0911
450
+ # R0911 Too many return statements (8/6)
451
+ stripped = line.lstrip()
452
+ if stripped.startswith('"""') or stripped.startswith("'''"):
453
+ self.state = "multiline"
454
+ self.multiline_start = self.line
455
+ self.multiline_terminator = stripped[:3]
456
+ self.multiline_leading = line.index(stripped[0])
457
+ return True
458
+
459
+ line = line.strip()
460
+ step = self.parse_step(line)
461
+ if step:
462
+ self.statement.steps.append(step)
463
+ return True
464
+
465
+ if self.subaction_detect_taggable_statement(line):
466
+ # -- DETECTED: Next Scenario, ScenarioOutline or Examples (or tags)
467
+ return True
468
+
469
+ if line.startswith("|"):
470
+ assert self.statement.steps, "TABLE-START without step detected."
471
+ self.state = "table"
472
+ return self.action_table(line)
473
+
474
+ return False
475
+
476
+ def action_multiline(self, line):
477
+ if line.strip().startswith(self.multiline_terminator):
478
+ step = self.statement.steps[-1]
479
+ step.text = model.Text(u"\n".join(self.lines), u"text/plain",
480
+ self.multiline_start)
481
+ if step.name.endswith(":"):
482
+ step.name = step.name[:-1]
483
+ self.lines = []
484
+ self.multiline_terminator = None
485
+ self.state = "steps"
486
+ return True
487
+
488
+ self.lines.append(line[self.multiline_leading:])
489
+ # -- BETTER DIAGNOSTICS: May remove non-whitespace in execute_steps()
490
+ removed_line_prefix = line[:self.multiline_leading]
491
+ if removed_line_prefix.strip():
492
+ message = u"BAD-INDENT in multiline text: "
493
+ message += u"Line '%s' would strip leading '%s'" % \
494
+ (line, removed_line_prefix)
495
+ raise ParserError(message, self.line, self.filename)
496
+ return True
497
+
498
+ def action_table(self, line):
499
+ line = line.strip()
500
+
501
+ if not line.startswith("|"):
502
+ if self.examples:
503
+ self.examples.table = self.table
504
+ self.examples = None
505
+ else:
506
+ step = self.statement.steps[-1]
507
+ step.table = self.table
508
+ if step.name.endswith(":"):
509
+ step.name = step.name[:-1]
510
+ self.table = None
511
+ self.state = "steps"
512
+ return self.action_steps(line)
513
+
514
+ # -- SUPPORT: Escaped-pipe(s) in Gherkin cell values.
515
+ # Search for pipe(s) that are not preceeded with an escape char.
516
+ cells = [cell.replace("\\|", "|").strip()
517
+ for cell in re.split(r"(?<!\\)\|", line[1:-1])]
518
+ if self.table is None:
519
+ self.table = model.Table(cells, self.line)
520
+ else:
521
+ if len(cells) != len(self.table.headings):
522
+ raise ParserError(u"Malformed table", self.line)
523
+ self.table.add_row(cells, self.line)
524
+ return True
525
+
526
+ def match_keyword(self, keyword, line):
527
+ if not self.keywords:
528
+ self.language = DEFAULT_LANGUAGE
529
+ self.keywords = i18n.languages[DEFAULT_LANGUAGE]
530
+ for alias in self.keywords[keyword]:
531
+ if line.startswith(alias + ":"):
532
+ return alias
533
+ return False
534
+
535
+ def parse_tags(self, line):
536
+ """
537
+ Parse a line with one or more tags:
538
+
539
+ * A tag starts with the AT sign.
540
+ * A tag consists of one word without whitespace chars.
541
+ * Multiple tags are separated with whitespace chars
542
+ * End-of-line comment is stripped.
543
+
544
+ :param line: Line with one/more tags to process.
545
+ :raise ParserError: If syntax error is detected.
546
+ """
547
+ assert line.startswith("@")
548
+ tags = []
549
+ for word in line.split():
550
+ if word.startswith("@"):
551
+ tags.append(model.Tag(word[1:], self.line))
552
+ elif word.startswith("#"):
553
+ break # -- COMMENT: Skip rest of line.
554
+ else:
555
+ # -- BAD-TAG: Abort here.
556
+ raise ParserError(u"tag: %s (line: %s)" % (word, line),
557
+ self.line, self.filename)
558
+ return tags
559
+
560
+ def parse_step(self, line):
561
+ for step_type in ("given", "when", "then", "and", "but"):
562
+ for kw in self.keywords[step_type]:
563
+ if kw.endswith("<"):
564
+ whitespace = ""
565
+ kw = kw[:-1]
566
+ else:
567
+ whitespace = " "
568
+
569
+ # try to match the keyword; also attempt a purely lowercase
570
+ # match if that'll work
571
+ if not (line.startswith(kw + whitespace)
572
+ or line.lower().startswith(kw.lower() + whitespace)):
573
+ continue
574
+
575
+ name = line[len(kw):].strip()
576
+ if step_type in ("and", "but"):
577
+ if not self.last_step:
578
+ raise ParserError(u"No previous step", self.line)
579
+ step_type = self.last_step
580
+ else:
581
+ self.last_step = step_type
582
+ step = model.Step(self.filename, self.line, kw, step_type,
583
+ name)
584
+ return step
585
+ return None
586
+
587
+ def parse_steps(self, text, filename=None):
588
+ """
589
+ Parse support for execute_steps() functionality that supports step with:
590
+ * multiline text
591
+ * table
592
+
593
+ :param text: Text that contains 0..* steps
594
+ :return: List of parsed steps (as model.Step objects).
595
+ """
596
+ assert isinstance(text, six.text_type)
597
+ if not self.language:
598
+ self.language = DEFAULT_LANGUAGE
599
+ self.reset()
600
+ self.filename = filename
601
+ self.statement = model.Scenario(filename, 0, u"scenario", u"")
602
+ self.state = "steps"
603
+
604
+ for line in text.split("\n"):
605
+ self.line += 1
606
+ if not line.strip() and self.state != "multiline":
607
+ # -- SKIP EMPTY LINES, except in multiline string args.
608
+ continue
609
+ self.action(line)
610
+
611
+ # -- FINALLY:
612
+ if self.table:
613
+ self.action_table("")
614
+ steps = self.statement.steps
615
+ return steps