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.
- checksums.yaml +7 -0
- data/.cane +0 -0
- data/.gitignore +17 -0
- data/.tailor +4 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE +15 -0
- data/README.md +41 -0
- data/Rakefile +68 -0
- data/busser-behave.gemspec +30 -0
- data/features/plugin_install_command.feature +11 -0
- data/features/plugin_list_command.feature +8 -0
- data/features/support/env.rb +13 -0
- data/features/test_command.feature +31 -0
- data/lib/busser/behave/version.rb +26 -0
- data/lib/busser/runner_plugin/behave.rb +37 -0
- data/vendor/behave/CHANGES.rst +483 -0
- data/vendor/behave/LICENSE +23 -0
- data/vendor/behave/MANIFEST.in +37 -0
- data/vendor/behave/PROJECT_INFO.rst +21 -0
- data/vendor/behave/README.rst +112 -0
- data/vendor/behave/VERSION.txt +1 -0
- data/vendor/behave/behave.ini +22 -0
- data/vendor/behave/behave/__init__.py +30 -0
- data/vendor/behave/behave/__main__.py +187 -0
- data/vendor/behave/behave/_stepimport.py +185 -0
- data/vendor/behave/behave/_types.py +134 -0
- data/vendor/behave/behave/api/__init__.py +7 -0
- data/vendor/behave/behave/api/async_step.py +283 -0
- data/vendor/behave/behave/capture.py +227 -0
- data/vendor/behave/behave/compat/__init__.py +5 -0
- data/vendor/behave/behave/compat/collections.py +20 -0
- data/vendor/behave/behave/configuration.py +788 -0
- data/vendor/behave/behave/contrib/__init__.py +0 -0
- data/vendor/behave/behave/contrib/scenario_autoretry.py +73 -0
- data/vendor/behave/behave/formatter/__init__.py +12 -0
- data/vendor/behave/behave/formatter/_builtins.py +39 -0
- data/vendor/behave/behave/formatter/_registry.py +135 -0
- data/vendor/behave/behave/formatter/ansi_escapes.py +91 -0
- data/vendor/behave/behave/formatter/base.py +200 -0
- data/vendor/behave/behave/formatter/formatters.py +57 -0
- data/vendor/behave/behave/formatter/json.py +253 -0
- data/vendor/behave/behave/formatter/null.py +12 -0
- data/vendor/behave/behave/formatter/plain.py +158 -0
- data/vendor/behave/behave/formatter/pretty.py +351 -0
- data/vendor/behave/behave/formatter/progress.py +287 -0
- data/vendor/behave/behave/formatter/rerun.py +114 -0
- data/vendor/behave/behave/formatter/sphinx_steps.py +372 -0
- data/vendor/behave/behave/formatter/sphinx_util.py +118 -0
- data/vendor/behave/behave/formatter/steps.py +497 -0
- data/vendor/behave/behave/formatter/tags.py +178 -0
- data/vendor/behave/behave/i18n.py +614 -0
- data/vendor/behave/behave/importer.py +102 -0
- data/vendor/behave/behave/json_parser.py +264 -0
- data/vendor/behave/behave/log_capture.py +233 -0
- data/vendor/behave/behave/matchers.py +402 -0
- data/vendor/behave/behave/model.py +1737 -0
- data/vendor/behave/behave/model_core.py +416 -0
- data/vendor/behave/behave/model_describe.py +105 -0
- data/vendor/behave/behave/parser.py +615 -0
- data/vendor/behave/behave/reporter/__init__.py +0 -0
- data/vendor/behave/behave/reporter/base.py +45 -0
- data/vendor/behave/behave/reporter/junit.py +473 -0
- data/vendor/behave/behave/reporter/summary.py +94 -0
- data/vendor/behave/behave/runner.py +753 -0
- data/vendor/behave/behave/runner_util.py +417 -0
- data/vendor/behave/behave/step_registry.py +112 -0
- data/vendor/behave/behave/tag_expression.py +111 -0
- data/vendor/behave/behave/tag_matcher.py +465 -0
- data/vendor/behave/behave/textutil.py +137 -0
- data/vendor/behave/behave/userdata.py +130 -0
- data/vendor/behave/behave4cmd0/__all_steps__.py +12 -0
- data/vendor/behave/behave4cmd0/__init__.py +5 -0
- data/vendor/behave/behave4cmd0/__setup.py +11 -0
- data/vendor/behave/behave4cmd0/command_shell.py +216 -0
- data/vendor/behave/behave4cmd0/command_shell_proc.py +256 -0
- data/vendor/behave/behave4cmd0/command_steps.py +532 -0
- data/vendor/behave/behave4cmd0/command_util.py +147 -0
- data/vendor/behave/behave4cmd0/failing_steps.py +49 -0
- data/vendor/behave/behave4cmd0/log/__init__.py +1 -0
- data/vendor/behave/behave4cmd0/log/steps.py +395 -0
- data/vendor/behave/behave4cmd0/note_steps.py +29 -0
- data/vendor/behave/behave4cmd0/passing_steps.py +36 -0
- data/vendor/behave/behave4cmd0/pathutil.py +146 -0
- data/vendor/behave/behave4cmd0/setup_command_shell.py +24 -0
- data/vendor/behave/behave4cmd0/textutil.py +304 -0
- data/vendor/behave/bin/behave +44 -0
- data/vendor/behave/bin/behave.cmd +10 -0
- data/vendor/behave/bin/behave.junit_filter.py +85 -0
- data/vendor/behave/bin/behave.step_durations.py +163 -0
- data/vendor/behave/bin/behave2cucumber_json.py +63 -0
- data/vendor/behave/bin/behave_cmd.py +44 -0
- data/vendor/behave/bin/convert_i18n_yaml.py +77 -0
- data/vendor/behave/bin/explore_platform_encoding.py +24 -0
- data/vendor/behave/bin/i18n.yml +621 -0
- data/vendor/behave/bin/invoke +8 -0
- data/vendor/behave/bin/invoke.cmd +9 -0
- data/vendor/behave/bin/json.format.py +167 -0
- data/vendor/behave/bin/jsonschema_validate.py +122 -0
- data/vendor/behave/bin/make_localpi.py +279 -0
- data/vendor/behave/bin/project_bootstrap.sh +30 -0
- data/vendor/behave/bin/toxcmd.py +270 -0
- data/vendor/behave/bin/toxcmd3.py +270 -0
- data/vendor/behave/conftest.py +27 -0
- data/vendor/behave/docs/Makefile +154 -0
- data/vendor/behave/docs/_static/agogo.css +501 -0
- data/vendor/behave/docs/_static/behave_logo.png +0 -0
- data/vendor/behave/docs/_static/behave_logo1.png +0 -0
- data/vendor/behave/docs/_static/behave_logo2.png +0 -0
- data/vendor/behave/docs/_static/behave_logo3.png +0 -0
- data/vendor/behave/docs/_themes/LICENSE +45 -0
- data/vendor/behave/docs/_themes/kr/layout.html +17 -0
- data/vendor/behave/docs/_themes/kr/relations.html +19 -0
- data/vendor/behave/docs/_themes/kr/static/flasky.css_t +480 -0
- data/vendor/behave/docs/_themes/kr/static/small_flask.css +90 -0
- data/vendor/behave/docs/_themes/kr/theme.conf +7 -0
- data/vendor/behave/docs/_themes/kr_small/layout.html +22 -0
- data/vendor/behave/docs/_themes/kr_small/static/flasky.css_t +287 -0
- data/vendor/behave/docs/_themes/kr_small/theme.conf +10 -0
- data/vendor/behave/docs/api.rst +408 -0
- data/vendor/behave/docs/appendix.rst +19 -0
- data/vendor/behave/docs/behave.rst +640 -0
- data/vendor/behave/docs/behave.rst-template +86 -0
- data/vendor/behave/docs/behave_ecosystem.rst +81 -0
- data/vendor/behave/docs/comparison.rst +85 -0
- data/vendor/behave/docs/conf.py +293 -0
- data/vendor/behave/docs/context_attributes.rst +66 -0
- data/vendor/behave/docs/django.rst +192 -0
- data/vendor/behave/docs/formatters.rst +61 -0
- data/vendor/behave/docs/gherkin.rst +673 -0
- data/vendor/behave/docs/index.rst +57 -0
- data/vendor/behave/docs/install.rst +60 -0
- data/vendor/behave/docs/more_info.rst +184 -0
- data/vendor/behave/docs/new_and_noteworthy.rst +18 -0
- data/vendor/behave/docs/new_and_noteworthy_v1.2.4.rst +11 -0
- data/vendor/behave/docs/new_and_noteworthy_v1.2.5.rst +814 -0
- data/vendor/behave/docs/new_and_noteworthy_v1.2.6.rst +255 -0
- data/vendor/behave/docs/parse_builtin_types.rst +59 -0
- data/vendor/behave/docs/philosophy.rst +235 -0
- data/vendor/behave/docs/regular_expressions.rst +71 -0
- data/vendor/behave/docs/related.rst +14 -0
- data/vendor/behave/docs/test_domains.rst +62 -0
- data/vendor/behave/docs/tutorial.rst +636 -0
- data/vendor/behave/docs/update_behave_rst.py +100 -0
- data/vendor/behave/etc/json/behave.json-schema +172 -0
- data/vendor/behave/etc/junit.xml/behave_junit.xsd +103 -0
- data/vendor/behave/etc/junit.xml/junit-4.xsd +92 -0
- data/vendor/behave/examples/async_step/README.txt +8 -0
- data/vendor/behave/examples/async_step/behave.ini +14 -0
- data/vendor/behave/examples/async_step/features/async_dispatch.feature +8 -0
- data/vendor/behave/examples/async_step/features/async_run.feature +6 -0
- data/vendor/behave/examples/async_step/features/environment.py +28 -0
- data/vendor/behave/examples/async_step/features/steps/async_dispatch_steps.py +26 -0
- data/vendor/behave/examples/async_step/features/steps/async_steps34.py +10 -0
- data/vendor/behave/examples/async_step/features/steps/async_steps35.py +10 -0
- data/vendor/behave/examples/async_step/testrun_example.async_dispatch.txt +11 -0
- data/vendor/behave/examples/async_step/testrun_example.async_run.txt +9 -0
- data/vendor/behave/examples/env_vars/README.rst +26 -0
- data/vendor/behave/examples/env_vars/behave.ini +15 -0
- data/vendor/behave/examples/env_vars/behave_run.output_example.txt +12 -0
- data/vendor/behave/examples/env_vars/features/env_var.feature +6 -0
- data/vendor/behave/examples/env_vars/features/steps/env_var_steps.py +38 -0
- data/vendor/behave/features/README.txt +12 -0
- data/vendor/behave/features/background.feature +392 -0
- data/vendor/behave/features/capture_stderr.feature +172 -0
- data/vendor/behave/features/capture_stdout.feature +125 -0
- data/vendor/behave/features/cmdline.lang_list.feature +33 -0
- data/vendor/behave/features/configuration.default_paths.feature +116 -0
- data/vendor/behave/features/context.global_params.feature +35 -0
- data/vendor/behave/features/context.local_params.feature +17 -0
- data/vendor/behave/features/directory_layout.advanced.feature +147 -0
- data/vendor/behave/features/directory_layout.basic.feature +75 -0
- data/vendor/behave/features/directory_layout.basic2.feature +87 -0
- data/vendor/behave/features/environment.py +53 -0
- data/vendor/behave/features/exploratory_testing.with_table.feature +141 -0
- data/vendor/behave/features/feature.description.feature +0 -0
- data/vendor/behave/features/feature.exclude_from_run.feature +96 -0
- data/vendor/behave/features/formatter.help.feature +30 -0
- data/vendor/behave/features/formatter.json.feature +420 -0
- data/vendor/behave/features/formatter.progress3.feature +235 -0
- data/vendor/behave/features/formatter.rerun.feature +296 -0
- data/vendor/behave/features/formatter.steps.feature +181 -0
- data/vendor/behave/features/formatter.steps_catalog.feature +100 -0
- data/vendor/behave/features/formatter.steps_doc.feature +140 -0
- data/vendor/behave/features/formatter.steps_usage.feature +404 -0
- data/vendor/behave/features/formatter.tags.feature +134 -0
- data/vendor/behave/features/formatter.tags_location.feature +183 -0
- data/vendor/behave/features/formatter.user_defined.feature +196 -0
- data/vendor/behave/features/i18n.unicode_problems.feature +445 -0
- data/vendor/behave/features/logcapture.clear_handlers.feature +114 -0
- data/vendor/behave/features/logcapture.feature +188 -0
- data/vendor/behave/features/logcapture.filter.feature +130 -0
- data/vendor/behave/features/logging.no_capture.feature +99 -0
- data/vendor/behave/features/logging.setup_format.feature +157 -0
- data/vendor/behave/features/logging.setup_level.feature +168 -0
- data/vendor/behave/features/logging.setup_with_configfile.feature +137 -0
- data/vendor/behave/features/parser.background.sad_cases.feature +129 -0
- data/vendor/behave/features/parser.feature.sad_cases.feature +144 -0
- data/vendor/behave/features/runner.abort_by_user.feature +305 -0
- data/vendor/behave/features/runner.continue_after_failed_step.feature +136 -0
- data/vendor/behave/features/runner.default_format.feature +175 -0
- data/vendor/behave/features/runner.dry_run.feature +184 -0
- data/vendor/behave/features/runner.feature_listfile.feature +223 -0
- data/vendor/behave/features/runner.hook_errors.feature +382 -0
- data/vendor/behave/features/runner.multiple_formatters.feature +285 -0
- data/vendor/behave/features/runner.scenario_autoretry.feature +131 -0
- data/vendor/behave/features/runner.select_files_by_regexp.example.feature +71 -0
- data/vendor/behave/features/runner.select_files_by_regexp.feature +84 -0
- data/vendor/behave/features/runner.select_scenarios_by_file_location.feature +403 -0
- data/vendor/behave/features/runner.select_scenarios_by_name.feature +289 -0
- data/vendor/behave/features/runner.select_scenarios_by_tag.feature +225 -0
- data/vendor/behave/features/runner.stop_after_failure.feature +122 -0
- data/vendor/behave/features/runner.tag_logic.feature +67 -0
- data/vendor/behave/features/runner.unknown_formatter.feature +23 -0
- data/vendor/behave/features/runner.use_stage_implementations.feature +126 -0
- data/vendor/behave/features/scenario.description.feature +171 -0
- data/vendor/behave/features/scenario.exclude_from_run.feature +217 -0
- data/vendor/behave/features/scenario_outline.basics.feature +100 -0
- data/vendor/behave/features/scenario_outline.improved.feature +177 -0
- data/vendor/behave/features/scenario_outline.name_annotation.feature +157 -0
- data/vendor/behave/features/scenario_outline.parametrized.feature +401 -0
- data/vendor/behave/features/scenario_outline.tagged_examples.feature +118 -0
- data/vendor/behave/features/step.async_steps.feature +225 -0
- data/vendor/behave/features/step.duplicated_step.feature +106 -0
- data/vendor/behave/features/step.execute_steps.feature +59 -0
- data/vendor/behave/features/step.execute_steps.with_table.feature +65 -0
- data/vendor/behave/features/step.import_other_step_module.feature +103 -0
- data/vendor/behave/features/step.pending_steps.feature +128 -0
- data/vendor/behave/features/step.undefined_steps.feature +307 -0
- data/vendor/behave/features/step.use_step_library.feature +44 -0
- data/vendor/behave/features/step_dialect.generic_steps.feature +189 -0
- data/vendor/behave/features/step_dialect.given_when_then.feature +89 -0
- data/vendor/behave/features/step_param.builtin_types.with_float.feature +239 -0
- data/vendor/behave/features/step_param.builtin_types.with_integer.feature +305 -0
- data/vendor/behave/features/step_param.custom_types.feature +134 -0
- data/vendor/behave/features/steps/behave_active_tags_steps.py +86 -0
- data/vendor/behave/features/steps/behave_context_steps.py +67 -0
- data/vendor/behave/features/steps/behave_model_tag_logic_steps.py +105 -0
- data/vendor/behave/features/steps/behave_model_util.py +105 -0
- data/vendor/behave/features/steps/behave_select_files_steps.py +83 -0
- data/vendor/behave/features/steps/behave_tag_expression_steps.py +166 -0
- data/vendor/behave/features/steps/behave_undefined_steps.py +101 -0
- data/vendor/behave/features/steps/use_steplib_behave4cmd.py +12 -0
- data/vendor/behave/features/summary.undefined_steps.feature +114 -0
- data/vendor/behave/features/tags.active_tags.feature +385 -0
- data/vendor/behave/features/tags.default_tags.feature +104 -0
- data/vendor/behave/features/tags.tag_expression.feature +105 -0
- data/vendor/behave/features/userdata.feature +331 -0
- data/vendor/behave/invoke.yaml +21 -0
- data/vendor/behave/issue.features/README.txt +17 -0
- data/vendor/behave/issue.features/environment.py +97 -0
- data/vendor/behave/issue.features/issue0030.feature +21 -0
- data/vendor/behave/issue.features/issue0031.feature +16 -0
- data/vendor/behave/issue.features/issue0032.feature +28 -0
- data/vendor/behave/issue.features/issue0035.feature +74 -0
- data/vendor/behave/issue.features/issue0040.feature +154 -0
- data/vendor/behave/issue.features/issue0041.feature +135 -0
- data/vendor/behave/issue.features/issue0042.feature +230 -0
- data/vendor/behave/issue.features/issue0044.feature +51 -0
- data/vendor/behave/issue.features/issue0046.feature +77 -0
- data/vendor/behave/issue.features/issue0052.feature +66 -0
- data/vendor/behave/issue.features/issue0059.feature +29 -0
- data/vendor/behave/issue.features/issue0063.feature +102 -0
- data/vendor/behave/issue.features/issue0064.feature +97 -0
- data/vendor/behave/issue.features/issue0065.feature +18 -0
- data/vendor/behave/issue.features/issue0066.feature +80 -0
- data/vendor/behave/issue.features/issue0067.feature +90 -0
- data/vendor/behave/issue.features/issue0069.feature +64 -0
- data/vendor/behave/issue.features/issue0072.feature +32 -0
- data/vendor/behave/issue.features/issue0073.feature +228 -0
- data/vendor/behave/issue.features/issue0075.feature +18 -0
- data/vendor/behave/issue.features/issue0077.feature +89 -0
- data/vendor/behave/issue.features/issue0080.feature +49 -0
- data/vendor/behave/issue.features/issue0081.feature +138 -0
- data/vendor/behave/issue.features/issue0083.feature +69 -0
- data/vendor/behave/issue.features/issue0084.feature +69 -0
- data/vendor/behave/issue.features/issue0085.feature +119 -0
- data/vendor/behave/issue.features/issue0092.feature +66 -0
- data/vendor/behave/issue.features/issue0096.feature +173 -0
- data/vendor/behave/issue.features/issue0099.feature +130 -0
- data/vendor/behave/issue.features/issue0109.feature +60 -0
- data/vendor/behave/issue.features/issue0111.feature +53 -0
- data/vendor/behave/issue.features/issue0112.feature +64 -0
- data/vendor/behave/issue.features/issue0114.feature +118 -0
- data/vendor/behave/issue.features/issue0116.feature +71 -0
- data/vendor/behave/issue.features/issue0125.feature +49 -0
- data/vendor/behave/issue.features/issue0127.feature +64 -0
- data/vendor/behave/issue.features/issue0139.feature +67 -0
- data/vendor/behave/issue.features/issue0142.feature +37 -0
- data/vendor/behave/issue.features/issue0143.feature +54 -0
- data/vendor/behave/issue.features/issue0145.feature +63 -0
- data/vendor/behave/issue.features/issue0148.feature +105 -0
- data/vendor/behave/issue.features/issue0152.feature +52 -0
- data/vendor/behave/issue.features/issue0159.feature +74 -0
- data/vendor/behave/issue.features/issue0162.feature +86 -0
- data/vendor/behave/issue.features/issue0171.feature +16 -0
- data/vendor/behave/issue.features/issue0172.feature +51 -0
- data/vendor/behave/issue.features/issue0175.feature +91 -0
- data/vendor/behave/issue.features/issue0177.feature +40 -0
- data/vendor/behave/issue.features/issue0181.feature +36 -0
- data/vendor/behave/issue.features/issue0184.feature +144 -0
- data/vendor/behave/issue.features/issue0186.feature +12 -0
- data/vendor/behave/issue.features/issue0188.feature +60 -0
- data/vendor/behave/issue.features/issue0191.feature +178 -0
- data/vendor/behave/issue.features/issue0194.feature +215 -0
- data/vendor/behave/issue.features/issue0197.feature +11 -0
- data/vendor/behave/issue.features/issue0216.feature +129 -0
- data/vendor/behave/issue.features/issue0226.feature +51 -0
- data/vendor/behave/issue.features/issue0228.feature +41 -0
- data/vendor/behave/issue.features/issue0230.feature +46 -0
- data/vendor/behave/issue.features/issue0231.feature +77 -0
- data/vendor/behave/issue.features/issue0238.feature +52 -0
- data/vendor/behave/issue.features/issue0251.feature +15 -0
- data/vendor/behave/issue.features/issue0280.feature +118 -0
- data/vendor/behave/issue.features/issue0288.feature +95 -0
- data/vendor/behave/issue.features/issue0300.feature +49 -0
- data/vendor/behave/issue.features/issue0302.feature +91 -0
- data/vendor/behave/issue.features/issue0309.feature +52 -0
- data/vendor/behave/issue.features/issue0330.feature +124 -0
- data/vendor/behave/issue.features/issue0349.feature +9 -0
- data/vendor/behave/issue.features/issue0361.feature +79 -0
- data/vendor/behave/issue.features/issue0383.feature +76 -0
- data/vendor/behave/issue.features/issue0384.feature +103 -0
- data/vendor/behave/issue.features/issue0385.feature +109 -0
- data/vendor/behave/issue.features/issue0424.feature +66 -0
- data/vendor/behave/issue.features/issue0446.feature +116 -0
- data/vendor/behave/issue.features/issue0449.feature +42 -0
- data/vendor/behave/issue.features/issue0453.feature +42 -0
- data/vendor/behave/issue.features/issue0457.feature +65 -0
- data/vendor/behave/issue.features/issue0462.feature +38 -0
- data/vendor/behave/issue.features/issue0476.feature +39 -0
- data/vendor/behave/issue.features/issue0487.feature +92 -0
- data/vendor/behave/issue.features/issue0506.feature +77 -0
- data/vendor/behave/issue.features/issue0510.feature +51 -0
- data/vendor/behave/issue.features/requirements.txt +12 -0
- data/vendor/behave/issue.features/steps/ansi_steps.py +20 -0
- data/vendor/behave/issue.features/steps/behave_hooks_steps.py +10 -0
- data/vendor/behave/issue.features/steps/use_steplib_behave4cmd.py +13 -0
- data/vendor/behave/more.features/formatter.json.validate_output.feature +37 -0
- data/vendor/behave/more.features/steps/tutorial_steps.py +16 -0
- data/vendor/behave/more.features/steps/use_steplib_behave4cmd.py +7 -0
- data/vendor/behave/more.features/tutorial.feature +6 -0
- data/vendor/behave/py.requirements/README.txt +5 -0
- data/vendor/behave/py.requirements/all.txt +16 -0
- data/vendor/behave/py.requirements/basic.txt +21 -0
- data/vendor/behave/py.requirements/develop.txt +28 -0
- data/vendor/behave/py.requirements/docs.txt +6 -0
- data/vendor/behave/py.requirements/json.txt +7 -0
- data/vendor/behave/py.requirements/more_py26.txt +8 -0
- data/vendor/behave/py.requirements/testing.txt +10 -0
- data/vendor/behave/pytest.ini +24 -0
- data/vendor/behave/setup.cfg +29 -0
- data/vendor/behave/setup.py +118 -0
- data/vendor/behave/setuptools_behave.py +130 -0
- data/vendor/behave/tasks/__behave.py +45 -0
- data/vendor/behave/tasks/__init__.py +55 -0
- data/vendor/behave/tasks/__main__.py +70 -0
- data/vendor/behave/tasks/_setup.py +135 -0
- data/vendor/behave/tasks/_vendor/README.rst +35 -0
- data/vendor/behave/tasks/_vendor/invoke.zip +0 -0
- data/vendor/behave/tasks/_vendor/path.py +1725 -0
- data/vendor/behave/tasks/_vendor/pathlib.py +1280 -0
- data/vendor/behave/tasks/_vendor/six.py +868 -0
- data/vendor/behave/tasks/clean.py +246 -0
- data/vendor/behave/tasks/docs.py +97 -0
- data/vendor/behave/tasks/requirements.txt +17 -0
- data/vendor/behave/tasks/test.py +192 -0
- data/vendor/behave/test/__init__.py +0 -0
- data/vendor/behave/test/_importer_candidate.py +3 -0
- data/vendor/behave/test/reporters/__init__.py +0 -0
- data/vendor/behave/test/reporters/test_summary.py +240 -0
- data/vendor/behave/test/test_ansi_escapes.py +73 -0
- data/vendor/behave/test/test_configuration.py +172 -0
- data/vendor/behave/test/test_formatter.py +265 -0
- data/vendor/behave/test/test_formatter_progress.py +39 -0
- data/vendor/behave/test/test_formatter_rerun.py +97 -0
- data/vendor/behave/test/test_formatter_tags.py +57 -0
- data/vendor/behave/test/test_importer.py +151 -0
- data/vendor/behave/test/test_log_capture.py +29 -0
- data/vendor/behave/test/test_matchers.py +236 -0
- data/vendor/behave/test/test_model.py +871 -0
- data/vendor/behave/test/test_parser.py +1590 -0
- data/vendor/behave/test/test_runner.py +1074 -0
- data/vendor/behave/test/test_step_registry.py +96 -0
- data/vendor/behave/test/test_tag_expression.py +506 -0
- data/vendor/behave/test/test_tag_expression2.py +462 -0
- data/vendor/behave/test/test_tag_matcher.py +729 -0
- data/vendor/behave/test/test_userdata.py +184 -0
- data/vendor/behave/tests/README.txt +12 -0
- data/vendor/behave/tests/__init__.py +0 -0
- data/vendor/behave/tests/api/__ONLY_PY34_or_newer.txt +0 -0
- data/vendor/behave/tests/api/__init__.py +0 -0
- data/vendor/behave/tests/api/_test_async_step34.py +130 -0
- data/vendor/behave/tests/api/_test_async_step35.py +75 -0
- data/vendor/behave/tests/api/test_async_step.py +18 -0
- data/vendor/behave/tests/api/testing_support.py +94 -0
- data/vendor/behave/tests/api/testing_support_async.py +21 -0
- data/vendor/behave/tests/issues/test_issue0336.py +66 -0
- data/vendor/behave/tests/issues/test_issue0449.py +55 -0
- data/vendor/behave/tests/issues/test_issue0453.py +62 -0
- data/vendor/behave/tests/issues/test_issue0458.py +54 -0
- data/vendor/behave/tests/issues/test_issue0495.py +65 -0
- data/vendor/behave/tests/unit/__init__.py +0 -0
- data/vendor/behave/tests/unit/test_behave4cmd_command_shell_proc.py +135 -0
- data/vendor/behave/tests/unit/test_capture.py +280 -0
- data/vendor/behave/tests/unit/test_model_core.py +56 -0
- data/vendor/behave/tests/unit/test_textutil.py +267 -0
- data/vendor/behave/tools/test-features/background.feature +9 -0
- data/vendor/behave/tools/test-features/environment.py +8 -0
- data/vendor/behave/tools/test-features/french.feature +11 -0
- data/vendor/behave/tools/test-features/outline.feature +39 -0
- data/vendor/behave/tools/test-features/parse.feature +10 -0
- data/vendor/behave/tools/test-features/step-data.feature +60 -0
- data/vendor/behave/tools/test-features/steps/steps.py +120 -0
- data/vendor/behave/tools/test-features/tags.feature +18 -0
- data/vendor/behave/tox.ini +159 -0
- metadata +562 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
|
2
|
+
"""Basic types (helper classes)."""
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import six
|
|
6
|
+
if six.PY2:
|
|
7
|
+
# -- USE PYTHON2 BACKPORT: With unicode support
|
|
8
|
+
import traceback2 as traceback
|
|
9
|
+
else:
|
|
10
|
+
import traceback
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Unknown(object):
|
|
14
|
+
"""Placeholder for unknown/missing information, distinguishable from None.
|
|
15
|
+
|
|
16
|
+
.. code-block:: python
|
|
17
|
+
|
|
18
|
+
data = {}
|
|
19
|
+
value = data.get("name", Unknown)
|
|
20
|
+
if value is Unknown:
|
|
21
|
+
# -- DO SOMETHING
|
|
22
|
+
...
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ExceptionUtil(object):
|
|
27
|
+
"""Provides a utility class for accessing/modifying exception information.
|
|
28
|
+
|
|
29
|
+
.. seealso:: PEP-3134 Chained excpetions
|
|
30
|
+
"""
|
|
31
|
+
# pylint: disable=no-init
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def get_traceback(exception):
|
|
35
|
+
# -- ASSUMPTION: assert isinstance(exception, Exception)
|
|
36
|
+
return getattr(exception, "__traceback__", None)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def set_traceback(exception, exc_traceback=Unknown):
|
|
40
|
+
assert isinstance(exception, Exception)
|
|
41
|
+
if exc_traceback is Unknown:
|
|
42
|
+
exc_traceback = sys.exc_info()[2]
|
|
43
|
+
exception.__traceback__ = exc_traceback
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def has_traceback(cls, exception):
|
|
47
|
+
"""Indicates if traceback information related to this exception
|
|
48
|
+
is stored with the exception object.
|
|
49
|
+
|
|
50
|
+
:param exception: Exception object to check.
|
|
51
|
+
:return: True, if traceback info is stored. False, otherwise.
|
|
52
|
+
"""
|
|
53
|
+
return cls.get_traceback(exception) is not None
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def describe(cls, exception, use_traceback=False, prefix=""):
|
|
57
|
+
# -- NORMAL CASE:
|
|
58
|
+
text = u"{prefix}{0}: {1}\n".format(exception.__class__.__name__,
|
|
59
|
+
exception, prefix=prefix)
|
|
60
|
+
if use_traceback:
|
|
61
|
+
exc_traceback = cls.get_traceback(exception)
|
|
62
|
+
if exc_traceback:
|
|
63
|
+
# -- NOTE: Chained-exception cause (see: PEP-3134).
|
|
64
|
+
text += u"".join(traceback.format_tb(exc_traceback))
|
|
65
|
+
return text
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ChainedExceptionUtil(ExceptionUtil):
|
|
69
|
+
"""Provides a utility class for accessing/modifying exception information
|
|
70
|
+
related to chained exceptions.
|
|
71
|
+
|
|
72
|
+
.. seealso:: PEP-3134 Chained excpetions
|
|
73
|
+
"""
|
|
74
|
+
# pylint: disable=no-init
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def get_cause(exception):
|
|
78
|
+
# -- ASSUMPTION: assert isinstance(exception, Exception)
|
|
79
|
+
return getattr(exception, "__cause__", None)
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def set_cause(exception, exc_cause):
|
|
83
|
+
assert isinstance(exception, Exception)
|
|
84
|
+
assert isinstance(exc_cause, Exception) or exc_cause is None
|
|
85
|
+
exception.__cause__ = exc_cause
|
|
86
|
+
if exc_cause and not hasattr(exc_cause, "__traceback__"):
|
|
87
|
+
# -- NEEDED-FOR: Python2
|
|
88
|
+
# Otherwise, traceback formatting tries to access missing attribute.
|
|
89
|
+
exc_cause.__traceback__ = None
|
|
90
|
+
|
|
91
|
+
# pylint: disable=arguments-differ
|
|
92
|
+
@classmethod
|
|
93
|
+
def describe(cls, exception, use_traceback=False, prefix="", style="reversed"):
|
|
94
|
+
"""Describes an exception, optionally together with its traceback info.
|
|
95
|
+
Also shows information about exception cause (chained exceptions),
|
|
96
|
+
if exists.
|
|
97
|
+
|
|
98
|
+
:param exception: Exception object to describe.
|
|
99
|
+
:param use_traceback: Indicates if traceback info should be shown.
|
|
100
|
+
:param prefix: Optional prefix for description text.
|
|
101
|
+
:param style: Optional style indicator ("reversed", "normal")
|
|
102
|
+
:return: Exception description as text.
|
|
103
|
+
"""
|
|
104
|
+
text = ExceptionUtil.describe(exception, use_traceback, prefix)
|
|
105
|
+
|
|
106
|
+
# -- STEP: Collect chained exceptions.
|
|
107
|
+
causes = []
|
|
108
|
+
exc_cause = cls.get_cause(exception)
|
|
109
|
+
while exc_cause:
|
|
110
|
+
causes.append(exc_cause)
|
|
111
|
+
exc_cause = cls.get_cause(exc_cause)
|
|
112
|
+
|
|
113
|
+
# -- STEP: Describe causes for chained exceptions.
|
|
114
|
+
parts = []
|
|
115
|
+
if style == "normal":
|
|
116
|
+
prefix = "CAUSE: "
|
|
117
|
+
for exc_cause in reversed(causes):
|
|
118
|
+
cause_text = ExceptionUtil.describe(exc_cause, use_traceback,
|
|
119
|
+
prefix)
|
|
120
|
+
parts.append(cause_text)
|
|
121
|
+
if len(parts) == 1:
|
|
122
|
+
prefix = "CAUSES: "
|
|
123
|
+
parts.append(text)
|
|
124
|
+
else:
|
|
125
|
+
parts.append(text)
|
|
126
|
+
for exc_cause in causes:
|
|
127
|
+
cause_text = ExceptionUtil.describe(exc_cause, use_traceback,
|
|
128
|
+
prefix="CAUSED-BY: ")
|
|
129
|
+
parts.append(cause_text)
|
|
130
|
+
return u"\n".join(parts)
|
|
131
|
+
# if exc_cause:
|
|
132
|
+
# cause_text =
|
|
133
|
+
# text += u"\n" + cause_text
|
|
134
|
+
# return text
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
|
2
|
+
# pylint: disable=line-too-long
|
|
3
|
+
"""
|
|
4
|
+
This module provides functionality to support "async steps" (coroutines)
|
|
5
|
+
in a step-module with behave. This functionality simplifies to test
|
|
6
|
+
frameworks and protocols that make use of `asyncio.coroutines`_ or
|
|
7
|
+
provide `asyncio.coroutines`_.
|
|
8
|
+
|
|
9
|
+
EXAMPLE:
|
|
10
|
+
|
|
11
|
+
.. code-block:: python
|
|
12
|
+
|
|
13
|
+
# -- FILE: features/steps/my_async_steps.py
|
|
14
|
+
# EXAMPLE REQUIRES: Python >= 3.5
|
|
15
|
+
from behave import step
|
|
16
|
+
from behave.api.async_step import async_run_until_complete
|
|
17
|
+
|
|
18
|
+
@step('an async coroutine step waits {duration:f} seconds')
|
|
19
|
+
@async_run_until_complete
|
|
20
|
+
async def step_async_step_waits_seconds(context, duration):
|
|
21
|
+
await asyncio.sleep(duration)
|
|
22
|
+
|
|
23
|
+
.. code-block:: python
|
|
24
|
+
|
|
25
|
+
# -- FILE: features/steps/my_async_steps2.py
|
|
26
|
+
# EXAMPLE REQUIRES: Python >= 3.4
|
|
27
|
+
from behave import step
|
|
28
|
+
from behave.api.async_step import async_run_until_complete
|
|
29
|
+
import asyncio
|
|
30
|
+
|
|
31
|
+
@step('a tagged-coroutine async step waits {duration:f} seconds')
|
|
32
|
+
@async_run_until_complete
|
|
33
|
+
@asyncio.coroutine
|
|
34
|
+
def step_async_step_waits_seconds2(context, duration):
|
|
35
|
+
yield from asyncio.sleep(duration)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
.. requires:: Python 3.5 (or 3.4) or :mod:`asyncio` backport (like :pypi:`trollius`)
|
|
39
|
+
.. seealso::
|
|
40
|
+
https://docs.python.org/3/library/asyncio.html
|
|
41
|
+
|
|
42
|
+
.. _asyncio.coroutines: https://docs.python.org/3/library/asyncio-task.html#coroutines
|
|
43
|
+
"""
|
|
44
|
+
# pylint: enable=line-too-long
|
|
45
|
+
|
|
46
|
+
from __future__ import print_function
|
|
47
|
+
# -- REQUIRES: Python >= 3.4
|
|
48
|
+
# MAYBE BACKPORT: trollius
|
|
49
|
+
import functools
|
|
50
|
+
from six import string_types
|
|
51
|
+
try:
|
|
52
|
+
import asyncio
|
|
53
|
+
has_asyncio = True
|
|
54
|
+
except ImportError:
|
|
55
|
+
has_asyncio = False
|
|
56
|
+
|
|
57
|
+
# -----------------------------------------------------------------------------
|
|
58
|
+
# ASYNC STEP DECORATORS:
|
|
59
|
+
# -----------------------------------------------------------------------------
|
|
60
|
+
def async_run_until_complete(astep_func=None, loop=None, timeout=None,
|
|
61
|
+
async_context=None, should_close=False):
|
|
62
|
+
"""Provides a function decorator for async-steps (coroutines).
|
|
63
|
+
Provides an async event loop and runs the async-step until completion
|
|
64
|
+
(or timeout, if specified).
|
|
65
|
+
|
|
66
|
+
.. code-block:: python
|
|
67
|
+
|
|
68
|
+
from behave import step
|
|
69
|
+
from behave.api.async_step import async_run_until_complete
|
|
70
|
+
import asyncio
|
|
71
|
+
|
|
72
|
+
@step("an async step is executed")
|
|
73
|
+
@async_run_until_complete
|
|
74
|
+
async def astep_impl(context)
|
|
75
|
+
await asycio.sleep(0.1)
|
|
76
|
+
|
|
77
|
+
@step("an async step is executed")
|
|
78
|
+
@async_run_until_complete(timeout=1.2)
|
|
79
|
+
async def astep_impl2(context)
|
|
80
|
+
# -- NOTE: Wrapped event loop waits with timeout=1.2 seconds.
|
|
81
|
+
await asycio.sleep(0.3)
|
|
82
|
+
|
|
83
|
+
Parameters:
|
|
84
|
+
astep_func: Async step function (coroutine)
|
|
85
|
+
loop (asyncio.EventLoop): Event loop to use or None.
|
|
86
|
+
timeout (int, float): Timeout to wait for async-step completion.
|
|
87
|
+
async_context (name): Async_context name or object to use.
|
|
88
|
+
should_close (bool): Indicates if event lopp should be closed.
|
|
89
|
+
|
|
90
|
+
.. note::
|
|
91
|
+
|
|
92
|
+
* If :param:`loop` is None, the default event loop will be used
|
|
93
|
+
or a new event loop is created.
|
|
94
|
+
* If :param:`timeout` is provided, the event loop waits only the
|
|
95
|
+
specified time.
|
|
96
|
+
* :param:`async_context` is only used, if :param:`loop` is None.
|
|
97
|
+
* If :param:`async_context` is a name, it will be used to retrieve
|
|
98
|
+
the real async_context object from the context.
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
@functools.wraps(astep_func)
|
|
102
|
+
def step_decorator(astep_func, context, *args, **kwargs):
|
|
103
|
+
loop = kwargs.pop("_loop", None)
|
|
104
|
+
timeout = kwargs.pop("_timeout", None)
|
|
105
|
+
async_context = kwargs.pop("_async_context", None)
|
|
106
|
+
should_close = kwargs.pop("_should_close", None)
|
|
107
|
+
|
|
108
|
+
if isinstance(loop, string_types):
|
|
109
|
+
loop = getattr(context, loop, None)
|
|
110
|
+
elif async_context:
|
|
111
|
+
if isinstance(async_context, string_types):
|
|
112
|
+
name = async_context
|
|
113
|
+
async_context = use_or_create_async_context(context, name)
|
|
114
|
+
loop = async_context.loop
|
|
115
|
+
else:
|
|
116
|
+
assert isinstance(async_context, AsyncContext)
|
|
117
|
+
loop = async_context.loop
|
|
118
|
+
if loop is None:
|
|
119
|
+
loop = asyncio.get_event_loop() or asyncio.new_event_loop()
|
|
120
|
+
|
|
121
|
+
# -- WORKHORSE:
|
|
122
|
+
try:
|
|
123
|
+
if timeout is None:
|
|
124
|
+
loop.run_until_complete(astep_func(context, *args, **kwargs))
|
|
125
|
+
else:
|
|
126
|
+
# MAYBE: loop = asyncio.new_event_loop()
|
|
127
|
+
# MAYBE: should_close = True
|
|
128
|
+
task = loop.create_task(astep_func(context, *args, **kwargs))
|
|
129
|
+
done, pending = loop.run_until_complete(
|
|
130
|
+
asyncio.wait([task], timeout=timeout))
|
|
131
|
+
assert not pending, "TIMEOUT-OCCURED: timeout=%s" % timeout
|
|
132
|
+
finally:
|
|
133
|
+
if loop and should_close:
|
|
134
|
+
# -- MAYBE-AVOID:
|
|
135
|
+
loop.close()
|
|
136
|
+
|
|
137
|
+
if astep_func is None:
|
|
138
|
+
# -- CASE: @decorator(timeout=1.2, ...)
|
|
139
|
+
# MAYBE: return functools.partial(step_decorator,
|
|
140
|
+
def wrapped_decorator1(astep_func):
|
|
141
|
+
@functools.wraps(astep_func)
|
|
142
|
+
def wrapped_decorator2(context, *args, **kwargs):
|
|
143
|
+
return step_decorator(astep_func, context, *args,
|
|
144
|
+
_loop=loop,
|
|
145
|
+
_timeout=timeout,
|
|
146
|
+
_async_context=async_context,
|
|
147
|
+
_should_close=should_close, **kwargs)
|
|
148
|
+
assert callable(astep_func)
|
|
149
|
+
return wrapped_decorator2
|
|
150
|
+
return wrapped_decorator1
|
|
151
|
+
else:
|
|
152
|
+
# -- CASE: @decorator ... or astep = decorator(astep)
|
|
153
|
+
# MAYBE: return functools.partial(step_decorator, astep_func=astep_func)
|
|
154
|
+
assert callable(astep_func)
|
|
155
|
+
@functools.wraps(astep_func)
|
|
156
|
+
def wrapped_decorator(context, *args, **kwargs):
|
|
157
|
+
return step_decorator(astep_func, context, *args, **kwargs)
|
|
158
|
+
return wrapped_decorator
|
|
159
|
+
|
|
160
|
+
# -- ALIAS:
|
|
161
|
+
run_until_complete = async_run_until_complete
|
|
162
|
+
|
|
163
|
+
# -----------------------------------------------------------------------------
|
|
164
|
+
# ASYNC STEP UTILITY CLASSES:
|
|
165
|
+
# -----------------------------------------------------------------------------
|
|
166
|
+
class AsyncContext(object):
|
|
167
|
+
# pylint: disable=line-too-long
|
|
168
|
+
"""Provides a context object for "async steps" to keep track:
|
|
169
|
+
|
|
170
|
+
* which event loop is used
|
|
171
|
+
* which (asyncio) tasks are used or of interest
|
|
172
|
+
|
|
173
|
+
.. attribute:: loop
|
|
174
|
+
Event loop object to use.
|
|
175
|
+
If none is provided, the current event-loop is used
|
|
176
|
+
(or a new one is created).
|
|
177
|
+
|
|
178
|
+
.. attribute:: tasks
|
|
179
|
+
List of started :mod:`asyncio` tasks (of interest).
|
|
180
|
+
|
|
181
|
+
.. attribute:: name
|
|
182
|
+
|
|
183
|
+
Optional name of this object (in the behave context).
|
|
184
|
+
If none is provided, :attr:`AsyncContext.default_name` is used.
|
|
185
|
+
|
|
186
|
+
.. attribute:: should_close
|
|
187
|
+
Indicates if the :attr:`loop` (event-loop) should be closed or not.
|
|
188
|
+
|
|
189
|
+
EXAMPLE:
|
|
190
|
+
|
|
191
|
+
.. code-block:: python
|
|
192
|
+
|
|
193
|
+
# -- FILE: features/steps/my_async_steps.py
|
|
194
|
+
# REQUIRES: Python 3.5
|
|
195
|
+
from behave import given, when, then, step
|
|
196
|
+
from behave.api.async_step import AsyncContext
|
|
197
|
+
|
|
198
|
+
@when('I dispatch an async-call with param "{param}"')
|
|
199
|
+
def step_impl(context, param):
|
|
200
|
+
async_context = getattr(context, "async_context", None)
|
|
201
|
+
if async_context is None:
|
|
202
|
+
async_context = context.async_context = AsyncContext()
|
|
203
|
+
task = async_context.loop.create_task(my_async_func(param))
|
|
204
|
+
async_context.tasks.append(task)
|
|
205
|
+
|
|
206
|
+
@then('I wait at most {duration:f} seconds until all async-calls are completed')
|
|
207
|
+
def step_impl(context, duration):
|
|
208
|
+
async_context = context.async_context
|
|
209
|
+
assert async_context.tasks
|
|
210
|
+
done, pending = async_context.loop.run_until_complete(asyncio.wait(
|
|
211
|
+
async_context.tasks, loop=async_context.loop, timeout=duration))
|
|
212
|
+
assert len(pending) == 0
|
|
213
|
+
|
|
214
|
+
# -- COROUTINE:
|
|
215
|
+
async def my_async_func(param):
|
|
216
|
+
await asyncio.sleep(0.5)
|
|
217
|
+
return param.upper()
|
|
218
|
+
"""
|
|
219
|
+
# pylint: enable=line-too-long
|
|
220
|
+
default_name = "async_context"
|
|
221
|
+
|
|
222
|
+
def __init__(self, loop=None, name=None, should_close=False, tasks=None):
|
|
223
|
+
self.loop = loop or asyncio.get_event_loop() or asyncio.new_event_loop()
|
|
224
|
+
self.tasks = tasks or []
|
|
225
|
+
self.name = name or self.default_name
|
|
226
|
+
self.should_close = should_close
|
|
227
|
+
|
|
228
|
+
def __del__(self):
|
|
229
|
+
if self.loop and self.should_close:
|
|
230
|
+
self.close()
|
|
231
|
+
|
|
232
|
+
def close(self):
|
|
233
|
+
if self.loop and not self.loop.is_closed():
|
|
234
|
+
self.loop.close()
|
|
235
|
+
self.loop = None
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# -----------------------------------------------------------------------------
|
|
239
|
+
# ASYNC STEP UTILITY FUNCTIONS:
|
|
240
|
+
# -----------------------------------------------------------------------------
|
|
241
|
+
def use_or_create_async_context(context, name=None, loop=None, **kwargs):
|
|
242
|
+
"""Utility function to be used in step implementations to ensure that an
|
|
243
|
+
:class:`AsyncContext` object is stored in the :param:`context` object.
|
|
244
|
+
|
|
245
|
+
If no such attribute exists (under the given name),
|
|
246
|
+
a new :class:`AsyncContext` object is created with the provided args.
|
|
247
|
+
Otherwise, the existing context attribute is used.
|
|
248
|
+
|
|
249
|
+
EXAMPLE:
|
|
250
|
+
|
|
251
|
+
.. code-block:: python
|
|
252
|
+
|
|
253
|
+
# -- FILE: features/steps/my_async_steps.py
|
|
254
|
+
# EXAMPLE REQUIRES: Python 3.5
|
|
255
|
+
from behave import when
|
|
256
|
+
from behave.api.async_step import use_or_create_async_context
|
|
257
|
+
|
|
258
|
+
@when('I dispatch an async-call with param "{param}"')
|
|
259
|
+
def step_impl(context, param):
|
|
260
|
+
async_context = use_or_create_async_context(context, "async_context")
|
|
261
|
+
task = async_context.loop.create_task(my_async_func(param))
|
|
262
|
+
async_context.tasks.append(task)
|
|
263
|
+
|
|
264
|
+
# -- COROUTINE:
|
|
265
|
+
async def my_async_func(param):
|
|
266
|
+
await asyncio.sleep(0.5)
|
|
267
|
+
return param.upper()
|
|
268
|
+
|
|
269
|
+
:param context: Behave context object to use.
|
|
270
|
+
:param name: Optional name of async-context object (as string or None).
|
|
271
|
+
:param loop: Optional event_loop object to use for create call.
|
|
272
|
+
:param kwargs: Optional :class:`AsyncContext` params for create call.
|
|
273
|
+
:return: :class:`AsyncContext` object from the param:`context`.
|
|
274
|
+
"""
|
|
275
|
+
if name is None:
|
|
276
|
+
name = AsyncContext.default_name
|
|
277
|
+
async_context = getattr(context, name, None)
|
|
278
|
+
if async_context is None:
|
|
279
|
+
async_context = AsyncContext(loop=loop, name=name, **kwargs)
|
|
280
|
+
setattr(context, async_context.name, async_context)
|
|
281
|
+
assert isinstance(async_context, AsyncContext)
|
|
282
|
+
assert getattr(context, async_context.name) is async_context
|
|
283
|
+
return async_context
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Capture output (stdout, stderr), logs, etc.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import absolute_import
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
import sys
|
|
9
|
+
from six import StringIO, PY2
|
|
10
|
+
from behave.log_capture import LoggingCapture
|
|
11
|
+
from behave.textutil import text as _text
|
|
12
|
+
|
|
13
|
+
def add_text_to(value, more_text, separator="\n"):
|
|
14
|
+
if more_text:
|
|
15
|
+
if value:
|
|
16
|
+
if separator and not value.endswith(separator):
|
|
17
|
+
value += separator
|
|
18
|
+
value += more_text
|
|
19
|
+
else:
|
|
20
|
+
value = more_text
|
|
21
|
+
return value
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Captured(object):
|
|
25
|
+
"""Stores and aggregates captured output data."""
|
|
26
|
+
empty = u""
|
|
27
|
+
linesep = u"\n"
|
|
28
|
+
|
|
29
|
+
def __init__(self, stdout=None, stderr=None, log_output=None):
|
|
30
|
+
self.stdout = stdout or self.empty
|
|
31
|
+
self.stderr = stderr or self.empty
|
|
32
|
+
self.log_output = log_output or self.empty
|
|
33
|
+
|
|
34
|
+
def reset(self):
|
|
35
|
+
self.stdout = self.empty
|
|
36
|
+
self.stderr = self.empty
|
|
37
|
+
self.log_output = self.empty
|
|
38
|
+
|
|
39
|
+
# -- PYTHON2:
|
|
40
|
+
if PY2:
|
|
41
|
+
def __nonzero__(self):
|
|
42
|
+
return bool(self.stdout or self.stderr or self.log_output)
|
|
43
|
+
else:
|
|
44
|
+
def __bool__(self):
|
|
45
|
+
return bool(self.stdout or self.stderr or self.log_output)
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def output(self):
|
|
49
|
+
"""Makes a simple report of the captured data by concatenating
|
|
50
|
+
all parts.
|
|
51
|
+
"""
|
|
52
|
+
output_text = self.stdout
|
|
53
|
+
output_text = add_text_to(output_text, self.stderr)
|
|
54
|
+
output_text = add_text_to(output_text, self.log_output)
|
|
55
|
+
return output_text
|
|
56
|
+
|
|
57
|
+
def add(self, captured):
|
|
58
|
+
"""Adds/appends captured output data to this object.
|
|
59
|
+
|
|
60
|
+
:param captured: Captured object whose data should be added.
|
|
61
|
+
:return: self, to allow daisy-chaining (if needed).
|
|
62
|
+
"""
|
|
63
|
+
assert isinstance(captured, Captured)
|
|
64
|
+
self.stdout = add_text_to(self.stdout, captured.stdout, self.linesep)
|
|
65
|
+
self.stderr = add_text_to(self.stderr, captured.stderr, self.linesep)
|
|
66
|
+
self.log_output = add_text_to(self.log_output, captured.log_output,
|
|
67
|
+
self.linesep)
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
def make_report(self):
|
|
71
|
+
"""Makes a detailled report of the captured output data.
|
|
72
|
+
|
|
73
|
+
:returns: Report as string.
|
|
74
|
+
"""
|
|
75
|
+
report_parts = []
|
|
76
|
+
if self.stdout:
|
|
77
|
+
parts = ["Captured stdout:", _text(self.stdout).rstrip(), ""]
|
|
78
|
+
report_parts.extend(parts)
|
|
79
|
+
if self.stderr:
|
|
80
|
+
parts = ["Captured stderr:", _text(self.stderr).rstrip(), ""]
|
|
81
|
+
report_parts.extend(parts)
|
|
82
|
+
if self.log_output:
|
|
83
|
+
parts = ["Captured logging:", _text(self.log_output)]
|
|
84
|
+
report_parts.extend(parts)
|
|
85
|
+
return self.linesep.join(report_parts).strip()
|
|
86
|
+
|
|
87
|
+
def __add__(self, other):
|
|
88
|
+
"""Supports incremental add::
|
|
89
|
+
|
|
90
|
+
captured1 = Captured("Hello")
|
|
91
|
+
captured2 = Captured("World")
|
|
92
|
+
captured3 = captured1 + captured2
|
|
93
|
+
assert captured3.stdout == "Hello\nWorld"
|
|
94
|
+
"""
|
|
95
|
+
new_data = Captured(self.stdout, self.stderr, self.log_output)
|
|
96
|
+
return new_data.add(other)
|
|
97
|
+
|
|
98
|
+
def __iadd__(self, other):
|
|
99
|
+
"""Supports incremental add::
|
|
100
|
+
|
|
101
|
+
captured1 = Captured("Hello")
|
|
102
|
+
captured2 = Captured("World")
|
|
103
|
+
captured1 += captured2
|
|
104
|
+
assert captured1.stdout == "Hello\nWorld"
|
|
105
|
+
"""
|
|
106
|
+
return self.add(other)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class CaptureController(object):
|
|
110
|
+
"""Simplifies the lifecycle to capture output from various sources."""
|
|
111
|
+
def __init__(self, config):
|
|
112
|
+
self.config = config
|
|
113
|
+
self.stdout_capture = None
|
|
114
|
+
self.stderr_capture = None
|
|
115
|
+
self.log_capture = None
|
|
116
|
+
self.old_stdout = None
|
|
117
|
+
self.old_stderr = None
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def captured(self):
|
|
121
|
+
"""Provides access of the captured output data.
|
|
122
|
+
|
|
123
|
+
:return: Object that stores the captured output parts (as Captured).
|
|
124
|
+
"""
|
|
125
|
+
stdout = None
|
|
126
|
+
stderr = None
|
|
127
|
+
log_out = None
|
|
128
|
+
if self.config.stdout_capture and self.stdout_capture:
|
|
129
|
+
stdout = _text(self.stdout_capture.getvalue())
|
|
130
|
+
if self.config.stderr_capture and self.stderr_capture:
|
|
131
|
+
stderr = _text(self.stderr_capture.getvalue())
|
|
132
|
+
if self.config.log_capture and self.log_capture:
|
|
133
|
+
log_out = _text(self.log_capture.getvalue())
|
|
134
|
+
return Captured(stdout, stderr, log_out)
|
|
135
|
+
|
|
136
|
+
def setup_capture(self, context):
|
|
137
|
+
assert context is not None
|
|
138
|
+
if self.config.stdout_capture:
|
|
139
|
+
self.stdout_capture = StringIO()
|
|
140
|
+
context.stdout_capture = self.stdout_capture
|
|
141
|
+
|
|
142
|
+
if self.config.stderr_capture:
|
|
143
|
+
self.stderr_capture = StringIO()
|
|
144
|
+
context.stderr_capture = self.stderr_capture
|
|
145
|
+
|
|
146
|
+
if self.config.log_capture:
|
|
147
|
+
self.log_capture = LoggingCapture(self.config)
|
|
148
|
+
self.log_capture.inveigle()
|
|
149
|
+
context.log_capture = self.log_capture
|
|
150
|
+
|
|
151
|
+
def start_capture(self):
|
|
152
|
+
if self.config.stdout_capture:
|
|
153
|
+
# -- REPLACE ONLY: In non-capturing mode.
|
|
154
|
+
if not self.old_stdout:
|
|
155
|
+
self.old_stdout = sys.stdout
|
|
156
|
+
sys.stdout = self.stdout_capture
|
|
157
|
+
assert sys.stdout is self.stdout_capture
|
|
158
|
+
|
|
159
|
+
if self.config.stderr_capture:
|
|
160
|
+
# -- REPLACE ONLY: In non-capturing mode.
|
|
161
|
+
if not self.old_stderr:
|
|
162
|
+
self.old_stderr = sys.stderr
|
|
163
|
+
sys.stderr = self.stderr_capture
|
|
164
|
+
assert sys.stderr is self.stderr_capture
|
|
165
|
+
|
|
166
|
+
def stop_capture(self):
|
|
167
|
+
if self.config.stdout_capture:
|
|
168
|
+
# -- RESTORE ONLY: In capturing mode.
|
|
169
|
+
if self.old_stdout:
|
|
170
|
+
sys.stdout = self.old_stdout
|
|
171
|
+
self.old_stdout = None
|
|
172
|
+
assert sys.stdout is not self.stdout_capture
|
|
173
|
+
|
|
174
|
+
if self.config.stderr_capture:
|
|
175
|
+
# -- RESTORE ONLY: In capturing mode.
|
|
176
|
+
if self.old_stderr:
|
|
177
|
+
sys.stderr = self.old_stderr
|
|
178
|
+
self.old_stderr = None
|
|
179
|
+
assert sys.stderr is not self.stderr_capture
|
|
180
|
+
|
|
181
|
+
def teardown_capture(self):
|
|
182
|
+
if self.config.log_capture:
|
|
183
|
+
self.log_capture.abandon()
|
|
184
|
+
|
|
185
|
+
def make_capture_report(self):
|
|
186
|
+
"""Combine collected output and return as string."""
|
|
187
|
+
return self.captured.make_report()
|
|
188
|
+
# report = u""
|
|
189
|
+
# if self.config.stdout_capture and self.stdout_capture:
|
|
190
|
+
# output = self.stdout_capture.getvalue()
|
|
191
|
+
# if output:
|
|
192
|
+
# output = _text(output)
|
|
193
|
+
# report += u"\nCaptured stdout:\n" + output
|
|
194
|
+
# if self.config.stderr_capture and self.stderr_capture:
|
|
195
|
+
# output = self.stderr_capture.getvalue()
|
|
196
|
+
# if output:
|
|
197
|
+
# output = _text(output)
|
|
198
|
+
# report += u"\nCaptured stderr:\n" + output
|
|
199
|
+
# if self.config.log_capture and self.log_capture:
|
|
200
|
+
# output = self.log_capture.getvalue()
|
|
201
|
+
# if output:
|
|
202
|
+
# output = _text(output)
|
|
203
|
+
# report += u"\nCaptured logging:\n" + output
|
|
204
|
+
# return report
|
|
205
|
+
|
|
206
|
+
# -----------------------------------------------------------------------------
|
|
207
|
+
# UTILITY FUNCTIONS:
|
|
208
|
+
# -----------------------------------------------------------------------------
|
|
209
|
+
@contextmanager
|
|
210
|
+
def capture_output(controller, enabled=True):
|
|
211
|
+
"""Provides a context manager that starts capturing output
|
|
212
|
+
|
|
213
|
+
.. code-block::
|
|
214
|
+
|
|
215
|
+
with capture_output(capture_controller):
|
|
216
|
+
... # Do something
|
|
217
|
+
"""
|
|
218
|
+
if enabled:
|
|
219
|
+
try:
|
|
220
|
+
controller.start_capture()
|
|
221
|
+
yield
|
|
222
|
+
finally:
|
|
223
|
+
controller.stop_capture()
|
|
224
|
+
else:
|
|
225
|
+
# -- CAPTURING OUTPUT is disabled.
|
|
226
|
+
# Needed to prevent recursive captures with context.execute_steps()
|
|
227
|
+
yield
|