Skip to content

Commit

Permalink
feat: Add strapp.click.sentry.capture_usage_errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Sosa committed Feb 24, 2023
1 parent 35dbdce commit 1450102
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "strapp"
version = "0.3.16"
version = "0.3.17"
description = ""
authors = []
packages = [
Expand Down
53 changes: 53 additions & 0 deletions src/strapp/click/sentry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import contextlib
from typing import Optional

import click
import sentry_sdk


class ClickProxy:
def __init__(self, cli, wrapper):
self.cli = cli
self.wrapper = wrapper

def __call__(self, *args, **kwargs):
with self.wrapper():
self.cli(*args, **kwargs)

def __getattr__(self, name):
return getattr(self.cli, name)

def main(self, *args, **kwargs):
"""Support testing via CliRunner.invoke."""
with self.wrapper():
self.cli.main(*args, **kwargs)


def capture_usage_errors(
dsn: Optional[str] = None,
environment: Optional[str] = None,
release: Optional[str] = None,
server_name: Optional[str] = None,
):
def decorator(cli):
@contextlib.contextmanager
def wrapper():
sentry_sdk.init(
dsn=dsn,
environment=environment,
release=release,
server_name=server_name,
)
try:
yield
except SystemExit as ex: # click throws SystemExits on CLI end-of-task
context = getattr(ex, "__context__")
if isinstance(context, click.exceptions.UsageError):
sentry_sdk.capture_exception(
click.exceptions.UsageError(context.format_message())
)
raise

return ClickProxy(cli, wrapper)

return decorator
35 changes: 35 additions & 0 deletions tests/click/test_sentry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from unittest.mock import call, patch

import click
from click.testing import CliRunner

from strapp.click import Resolver
from strapp.click.sentry import capture_usage_errors


def test_capture_usage_errors():
resolver = Resolver()

@capture_usage_errors(
dsn=None,
environment="environment",
release="release",
server_name="server_name",
)
@resolver.group()
def cli():
...

with patch("sentry_sdk.init") as mock_init:
with patch("sentry_sdk.capture_exception") as mock_capture:
CliRunner().invoke(cli, ["not-a-command"])

mock_init.assert_called_once_with(
dsn=None,
environment="environment",
release="release",
server_name="server_name",
)

mock_capture.assert_called_once()
mock_capture.call_args == call(click.exceptions.UsageError("No such command 'not-foo'."))

0 comments on commit 1450102

Please sign in to comment.