Skip to content

Commit

Permalink
feat: Show exceptions if they happened during loading a WSGI application
Browse files Browse the repository at this point in the history
  • Loading branch information
Stranger6667 committed Apr 27, 2020
1 parent d6d7695 commit 3de1d25
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 15 deletions.
9 changes: 9 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,18 @@ Changelog
`Unreleased`_
-------------

Added
~~~~~

- Show exceptions if they happened during loading a WSGI application. Option ``--show-errors-tracebacks`` will display a
full traceback.

`1.3.1`_ - 2020-04-27
---------------------

Fixed
~~~~~

- Packaging issue

`1.3.0`_ - 2020-04-27
Expand Down
8 changes: 7 additions & 1 deletion src/schemathesis/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,13 @@ def schemathesis(pre_run: Optional[str] = None) -> None:
)
@click.option("--validate-schema", help="Enable or disable validation of input schema.", type=bool, default=True)
@click.option("--junit-xml", help="Create junit-xml style report file at given path.", type=click.File("w"))
@click.option("--show-errors-tracebacks", help="Show full tracebacks for internal errors.", is_flag=True, default=False)
@click.option(
"--show-errors-tracebacks",
help="Show full tracebacks for internal errors.",
is_flag=True,
is_eager=True,
default=False,
)
@click.option("--store-network-log", help="Store requests and responses into a file", type=click.File("w"))
@click.option(
"--hypothesis-deadline",
Expand Down
14 changes: 9 additions & 5 deletions src/schemathesis/cli/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ def validate_app(ctx: click.core.Context, param: click.core.Parameter, raw_value
# Since most of app instances are not-transferable to another process, they are passed as strings and
# imported in a subprocess
return raw_value
except (ImportError, ValueError, AttributeError):
raise click.BadParameter("Can not import application from the given module")
except Exception as exc:
message = utils.format_exception(exc)
click.secho(f"Error: {message}", fg="red")
raise click.Abort
show_errors_tracebacks = ctx.params["show_errors_tracebacks"]
message = utils.format_exception(exc, show_errors_tracebacks)
click.secho(f"{message}\nCan not import application from the given module", fg="red")
if not show_errors_tracebacks:
click.secho(
"Add this option to your command line parameters to see full tracebacks: --show-errors-tracebacks",
fg="red",
)
raise click.exceptions.Exit(1)


def validate_auth(
Expand Down
4 changes: 2 additions & 2 deletions test/cli/test_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ def test_validate_auth(value):

@given(value=st.text())
def test_validate_app(value):
with pytest.raises(click.BadParameter):
callbacks.validate_app(None, None, value)
with pytest.raises(click.exceptions.Exit):
callbacks.validate_app(SimpleNamespace(params={"show_errors_tracebacks": False}), None, value)


@given(value=st.lists(st.text(), min_size=1).map(tuple))
Expand Down
14 changes: 7 additions & 7 deletions test/cli/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,9 +951,10 @@ def test_wsgi_app_exception(testdir, cli):
1 / 0
"""
)
result = cli.run("/swagger.yaml", "--app", f"{module.purebasename}:app")
result = cli.run("/swagger.yaml", "--app", f"{module.purebasename}:app", "--show-errors-tracebacks")
assert result.exit_code == ExitCode.TESTS_FAILED
assert result.stdout == "Error: ZeroDivisionError: division by zero\n\nAborted!\n"
assert "Traceback (most recent call last):" in result.stdout
assert "ZeroDivisionError: division by zero" in result.stdout


def test_wsgi_app_missing(testdir, cli):
Expand All @@ -963,11 +964,10 @@ def test_wsgi_app_missing(testdir, cli):
"""
)
result = cli.run("/swagger.yaml", "--app", f"{module.purebasename}:app")
assert result.exit_code == ExitCode.INTERRUPTED
assert (
result.stdout.strip().split("\n")[-1]
== "Error: Invalid value for '--app': Can not import application from the given module"
)
assert result.exit_code == ExitCode.TESTS_FAILED
lines = result.stdout.strip().split("\n")
assert "AttributeError: module 'location' has no attribute 'app'" in lines
assert "Can not import application from the given module" in lines


def test_wsgi_app_internal_exception(testdir, cli, caplog):
Expand Down

0 comments on commit 3de1d25

Please sign in to comment.