1+ import importlib
12import json
23import threading
34from unittest import mock
1314from sentry_sdk .integrations .logging import LoggingIntegration
1415import sentry_sdk .integrations .quart as quart_sentry
1516
16- from quart import Quart , Response , abort , stream_with_context
17- from quart .views import View
1817
19- from quart_auth import AuthUser , login_user
20-
21- try :
22- from quart_auth import QuartAuth
18+ def quart_app_factory ():
19+ # These imports are inlined because the `test_quart_flask_patch` testcase
20+ # tests behavior that is triggered by importing a package before any Quart
21+ # imports happen, so we can't have these on the module level
22+ from quart import Quart
2323
24- auth_manager = QuartAuth ()
25- except ImportError :
26- from quart_auth import AuthManager
24+ try :
25+ from quart_auth import QuartAuth
2726
28- auth_manager = AuthManager ()
27+ auth_manager = QuartAuth ()
28+ except ImportError :
29+ from quart_auth import AuthManager
2930
31+ auth_manager = AuthManager ()
3032
31- def quart_app_factory ():
3233 app = Quart (__name__ )
3334 app .debug = False
3435 app .config ["TESTING" ] = False
@@ -71,6 +72,42 @@ def integration_enabled_params(request):
7172 raise ValueError (request .param )
7273
7374
75+ @pytest .mark .asyncio
76+ @pytest .mark .forked
77+ @pytest .mark .skipif (
78+ not importlib .util .find_spec ("quart_flask_patch" ),
79+ reason = "requires quart_flask_patch" ,
80+ )
81+ async def test_quart_flask_patch (sentry_init , capture_events , reset_integrations ):
82+ # This testcase is forked because `import quart_flask_patch` needs to run
83+ # before anything else Quart-related is imported (since it monkeypatches
84+ # some things) and we don't want this to affect other testcases.
85+ #
86+ # It's also important this testcase be run before any other testcase
87+ # that uses `quart_app_factory`.
88+ import quart_flask_patch # noqa: F401
89+
90+ app = quart_app_factory ()
91+ sentry_init (
92+ integrations = [quart_sentry .QuartIntegration ()],
93+ )
94+
95+ @app .route ("/" )
96+ async def index ():
97+ 1 / 0
98+
99+ events = capture_events ()
100+
101+ client = app .test_client ()
102+ try :
103+ await client .get ("/" )
104+ except ZeroDivisionError :
105+ pass
106+
107+ (event ,) = events
108+ assert event ["exception" ]["values" ][0 ]["mechanism" ]["type" ] == "quart"
109+
110+
74111@pytest .mark .asyncio
75112async def test_has_context (sentry_init , capture_events ):
76113 sentry_init (integrations = [quart_sentry .QuartIntegration ()])
@@ -213,6 +250,8 @@ async def test_quart_auth_configured(
213250 monkeypatch ,
214251 integration_enabled_params ,
215252):
253+ from quart_auth import AuthUser , login_user
254+
216255 sentry_init (send_default_pii = send_default_pii , ** integration_enabled_params )
217256 app = quart_app_factory ()
218257
@@ -368,6 +407,8 @@ async def error_handler(err):
368407
369408@pytest .mark .asyncio
370409async def test_bad_request_not_captured (sentry_init , capture_events ):
410+ from quart import abort
411+
371412 sentry_init (integrations = [quart_sentry .QuartIntegration ()])
372413 app = quart_app_factory ()
373414 events = capture_events ()
@@ -385,6 +426,8 @@ async def index():
385426
386427@pytest .mark .asyncio
387428async def test_does_not_leak_scope (sentry_init , capture_events ):
429+ from quart import Response , stream_with_context
430+
388431 sentry_init (integrations = [quart_sentry .QuartIntegration ()])
389432 app = quart_app_factory ()
390433 events = capture_events ()
@@ -514,6 +557,8 @@ async def error():
514557
515558@pytest .mark .asyncio
516559async def test_class_based_views (sentry_init , capture_events ):
560+ from quart .views import View
561+
517562 sentry_init (integrations = [quart_sentry .QuartIntegration ()])
518563 app = quart_app_factory ()
519564 events = capture_events ()
0 commit comments