8000 fix: Close response correctly · etherscan-io/sentry-python@5f70a39 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5f70a39

Browse files
committed
fix: Close response correctly
Fixes getsentry#132
1 parent c44b2fe commit 5f70a39

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

sentry_sdk/integrations/_wsgi.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -178,34 +178,43 @@ def _capture_exception(hub):
178178

179179
@implements_iterator
180180
class _ScopePoppingResponse(object):
181-
__slots__ = ("_response", "_hub")
181+
__slots__ = ("_response", "_iterator", "_hub", "_popped")
182182

183183
def __init__(self, hub, response):
184184
self._hub = hub
185185
self._response = response
186+
self._iterator = None
187+
self._popped = False
186188

187189
def __iter__(self):
188190
try:
189-
self._response = iter(self._response)
191+
self._iterator = iter(self._response)
190192
except Exception:
191193
reraise(*_capture_exception(self.hub))
192194
return self
193195

194196
def __next__(self):
197+
if self._iterator is None:
198+
self.__iter__()
199+
195200
try:
196-
return next(self._response)
201+
return next(self._iterator)
197202
except StopIteration:
198203
raise
199204
except Exception:
200205
reraise(*_capture_exception(self.hub))
201206

202207
def close(self):
203-
self._hub.pop_scope_unsafe()
204-
if hasattr(self._response, "close"):
205-
try:
206-
self._response.close()
207-
except Exception:
208-
reraise(*_capture_exception(self.hub))
208+
if not self._popped:
209+
self._hub.pop_scope_unsafe()
210+
self._popped = True
211+
212+
try:
213+
self._response.close()
214+
except AttributeError:
215+
pass
216+
except Exception as e:
217+
reraise(*_capture_exception(self.hub))
209218

210219

211220
def _make_wsgi_event_processor(environ):

tests/integrations/wsgi/test_wsgi.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from werkzeug.test import Client
22
import pytest
33

4-
from sentry_sdk.integrations._wsgi import run_wsgi_app
4+
from sentry_sdk import Hub
5+
6+
from sentry_sdk.integrations._wsgi import run_wsgi_app, _ScopePoppingResponse
57

68

79
@pytest.fixture
@@ -31,3 +33,30 @@ def test_basic(sentry_init, crashing_app, capture_events):
3133
"method": "GET",
3234
"query_string": "",
3335
}
36+
37+
38+
def test_calls_close():
39+
hub = Hub.current
40+
stack_size = len(hub._stack)
41+
closes = []
42+
43+
hub.push_scope()
44+
45+
class Foo(object):
46+
def __iter__(self):
47+
yield 1
48+
yield 2
49+
yield 3
50+
51+
def close(self):
52+
closes.append(1)
53+
54+
response = _ScopePoppingResponse(hub, Foo())
55+
list(response)
56+
response.close()
57+
response.close()
58+
response.close()
59+
60+
# multiple close calls are just forwarded, but the scope is only popped once
61+
assert len(closes) == 3
62+
assert len(hub._stack) == stack_size

0 commit comments

Comments
 (0)
0