Skip to content

Commit d8766e6

Browse files
authored
fix: String keys (#90)
* fix: Coerce variable names to strings This already works fine right now because the JSON encoder coerces dictionary keys to strings, but we shouldn't rely on this behavior. * test: Assert that all keys are strings in event * fix: Bad assertion for empty dicts * fix: Allow all string types * fix: Linters
1 parent c5a8058 commit d8766e6

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

sentry_sdk/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def _walk(obj, depth):
297297
def extract_locals(frame):
298298
rv = {}
299299
for key, value in frame.f_locals.items():
300-
rv[key] = object_to_json(value)
300+
rv[str(key)] = object_to_json(value)
301301
return rv
302302

303303

tests/conftest.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pytest
66

77
import sentry_sdk
8-
from sentry_sdk._compat import reraise
8+
from sentry_sdk._compat import reraise, string_types
99
from sentry_sdk.transport import Transport
1010

1111
SEMAPHORE = "./semaphore"
@@ -31,10 +31,18 @@ def _capture_internal_exception(exc_info):
3131

3232
@pytest.fixture
3333
def monkeypatch_test_transport(monkeypatch, assert_semaphore_acceptance):
34+
def check_event(event):
35+
def check_string_keys(map):
36+
for key, value in map.items():
37+
assert isinstance(key, string_types)
38+
if isinstance(value, dict):
39+
check_string_keys(value)
40+
41+
check_string_keys(event)
42+
assert_semaphore_acceptance(event)
43+
3444
def inner(client):
35-
monkeypatch.setattr(
36-
client, "transport", TestTransport(assert_semaphore_acceptance)
37-
)
45+
monkeypatch.setattr(client, "transport", TestTransport(check_event))
3846

3947
return inner
4048

@@ -61,10 +69,9 @@ def inner(obj):
6169

6270
@pytest.fixture
6371
def assert_semaphore_acceptance(tmpdir):
64-
if not SEMAPHORE:
65-
return lambda event: None
66-
6772
def inner(event):
73+
if not SEMAPHORE:
74+
return
6875
# not dealing with the subprocess API right now
6976
file = tmpdir.join("event")
7077
file.write(json.dumps(dict(event)))
@@ -79,7 +86,7 @@ def inner(event):
7986

8087

8188
@pytest.fixture
82-
def sentry_init(monkeypatch_test_transport, assert_semaphore_acceptance):
89+
def sentry_init(monkeypatch_test_transport):
8390
def inner(*a, **kw):
8491
sentry_sdk.api._init_on_current(*a, **kw)
8592
monkeypatch_test_transport(sentry_sdk.Hub.current.client)

tests/test_utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,19 @@ def test_abs_path():
4040
for frame in frames:
4141
assert os.path.abspath(frame["abs_path"]) == frame["abs_path"]
4242
assert os.path.basename(frame["filename"]) == frame["filename"]
43+
44+
45+
def test_non_string_variables():
46+
"""There is some extremely terrible code in the wild that
47+
inserts non-strings as variable names into `locals()`."""
48+
49+
try:
50+
locals()[42] = True
51+
1 / 0
52+
except ZeroDivisionError:
53+
exceptions = exceptions_from_error_tuple(sys.exc_info())
54+
55+
exception, = exceptions
56+
assert exception["type"] == "ZeroDivisionError"
57+
frame, = exception["stacktrace"]["frames"]
58+
assert frame["vars"]["42"] == "True"

0 commit comments

Comments
 (0)