Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into potel-base
Browse files Browse the repository at this point in the history
  • Loading branch information
sl0thentr0py committed Dec 18, 2024
2 parents 7fca789 + 4e69cb7 commit 5a4bdde
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/test-integrations-misc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ jobs:
run: |
set -x # print commands that are executed
./scripts/runtox.sh "py${{ matrix.python-version }}-trytond-latest"
- name: Test typer latest
run: |
set -x # print commands that are executed
./scripts/runtox.sh "py${{ matrix.python-version }}-typer-latest"
- name: Generate coverage XML
if: ${{ !cancelled() }}
run: |
Expand Down Expand Up @@ -139,6 +143,10 @@ jobs:
run: |
set -x # print commands that are executed
./scripts/runtox.sh --exclude-latest "py${{ matrix.python-version }}-trytond"
- name: Test typer pinned
run: |
set -x # print commands that are executed
./scripts/runtox.sh --exclude-latest "py${{ matrix.python-version }}-typer"
- name: Generate coverage XML
if: ${{ !cancelled() }}
run: |
Expand Down
1 change: 1 addition & 0 deletions requirements-linting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pre-commit # local linting
httpcore
openfeature-sdk
launchdarkly-server-sdk
typer
1 change: 1 addition & 0 deletions scripts/split-tox-gh-actions/split-tox-gh-actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"potel",
"pure_eval",
"trytond",
"typer",
],
}

Expand Down
60 changes: 60 additions & 0 deletions sentry_sdk/integrations/typer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import sentry_sdk
from sentry_sdk.utils import (
capture_internal_exceptions,
event_from_exception,
)
from sentry_sdk.integrations import Integration, DidNotEnable

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Callable
from typing import Any
from typing import Type
from typing import Optional

from types import TracebackType

Excepthook = Callable[
[Type[BaseException], BaseException, Optional[TracebackType]],
Any,
]

try:
import typer
except ImportError:
raise DidNotEnable("Typer not installed")


class TyperIntegration(Integration):
identifier = "typer"

@staticmethod
def setup_once():
# type: () -> None
typer.main.except_hook = _make_excepthook(typer.main.except_hook) # type: ignore


def _make_excepthook(old_excepthook):
# type: (Excepthook) -> Excepthook
def sentry_sdk_excepthook(type_, value, traceback):
# type: (Type[BaseException], BaseException, Optional[TracebackType]) -> None
integration = sentry_sdk.get_client().get_integration(TyperIntegration)

# Note: If we replace this with ensure_integration_enabled then
# we break the exceptiongroup backport;
# See: https://github.com/getsentry/sentry-python/issues/3097
if integration is None:
return old_excepthook(type_, value, traceback)

with capture_internal_exceptions():
event, hint = event_from_exception(
(type_, value, traceback),
client_options=sentry_sdk.get_client().options,
mechanism={"type": "typer", "handled": False},
)
sentry_sdk.capture_event(event, hint=hint)

return old_excepthook(type_, value, traceback)

return sentry_sdk_excepthook
3 changes: 3 additions & 0 deletions tests/integrations/typer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pytest

pytest.importorskip("typer")
52 changes: 52 additions & 0 deletions tests/integrations/typer/test_typer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import subprocess
import sys
from textwrap import dedent
import pytest

from typer.testing import CliRunner

runner = CliRunner()


def test_catch_exceptions(tmpdir):
app = tmpdir.join("app.py")

app.write(
dedent(
"""
import typer
from unittest import mock
from sentry_sdk import init, transport
from sentry_sdk.integrations.typer import TyperIntegration
def capture_envelope(self, envelope):
print("capture_envelope was called")
event = envelope.get_event()
if event is not None:
print(event)
transport.HttpTransport.capture_envelope = capture_envelope
init("http://foobar@localhost/123", integrations=[TyperIntegration()])
app = typer.Typer()
@app.command()
def test():
print("test called")
raise Exception("pollo")
app()
"""
)
)

with pytest.raises(subprocess.CalledProcessError) as excinfo:
subprocess.check_output([sys.executable, str(app)], stderr=subprocess.STDOUT)

output = excinfo.value.output

assert b"capture_envelope was called" in output
assert b"test called" in output
assert b"pollo" in output
9 changes: 9 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ envlist =
{py3.8,py3.11,py3.12}-trytond-v{7}
{py3.8,py3.12,py3.13}-trytond-latest

# Typer
{py3.7,py3.12,py3.13}-typer-v{0.15}
{py3.7,py3.12,py3.13}-typer-latest

[testenv]
deps =
# if you change requirements-testing.txt and your change is not being reflected
Expand Down Expand Up @@ -716,6 +720,10 @@ deps =
trytond-v7: trytond~=7.0
trytond-latest: trytond

# Typer
typer-v0.15: typer~=0.15.0
typer-latest: typer

setenv =
PYTHONDONTWRITEBYTECODE=1
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
Expand Down Expand Up @@ -778,6 +786,7 @@ setenv =
strawberry: TESTPATH=tests/integrations/strawberry
tornado: TESTPATH=tests/integrations/tornado
trytond: TESTPATH=tests/integrations/trytond
typer: TESTPATH=tests/integrations/typer
socket: TESTPATH=tests/integrations/socket

passenv =
Expand Down

0 comments on commit 5a4bdde

Please sign in to comment.