fix(pymongo): decode bytes values instead of str()-ing them to avoid BytesWarning (#4782) - #7545
DawnofGenX wants to merge 2 commits into
Conversation
…rning Under `python -b`, stringify BSON bytes values (the `lsid` session id, a BSON `Binary`/`bytes` subclass, and bytes values inside commands serialized via `json.dumps(..., default=str)`) emits `BytesWarning: str() on a bytes instance` and produces useless `b'...'` strings. Route these conversions through a small `_bytes_safe_str()` helper that decodes UTF-8 with a replacement fallback for undecodable bytes, and adds regression tests that turn BytesWarning into an error. Fixes getsentry#4782
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e9b99e0. Configure here.
…g it The logical session id is a BSON Binary UUID (random bytes), not text. UTF-8-decoding it with errors='replace' is lossy and lets distinct ids collide, defeating its purpose as an identifier. Render it as hex instead, which is stable and lossless while still avoiding BytesWarning from str() (getsentry#4782, per Bugbot review). Co-Authored-By: Claude <noreply@anthropic.com>
|
Good catch — fixed in 3ef7ab5. The lsid is now rendered as a lossless hex string via a dedicated |

What
Under
python -b(BytesWarning mode), the PyMongo integration emitsBytesWarning: str() on a bytes instance— see #4782. The flagged line (data["operation_ids"]["session"] = str(lsid)in 2.37.0,str(lsid_id)on master) stringifies the BSON logical session id, which is abson.binary.Binary— abytessubclass. Two stringify sites inCommandTracer.started()have the same problem:str(lsid_id)→ session id becomes the literal string"b'...'"(plus BytesWarning under-b).json.dumps(command, default=str)→ any rawbytesvalue in the command (e.g. a bytes collection name, as reported) goes throughstr()the same way.How
_bytes_safe_str():value.decode("utf-8", errors="replace")forbytes(and subclasses likeBinary), plainstr()otherwise. Undecodable bytes get U+FFFD replacements instead of an exception; nothing is caught or hidden — the actual stringification is fixed.Tests
New regression tests in
tests/integrations/pymongo/test_pymongo.py:test_bytes_safe_str— helper unit test (decode, invalid-UTF-8 fallback, non-bytes passthrough).test_bytes_lsid_does_not_raise_byteswarning(PII on/off) — drivesCommandTracer.started()with aBinarylsid underwarnings.simplefilter("error", BytesWarning)and assertsoperation_ids.sessionis a clean decodedstr, nob'prefix.test_bytes_collection_name_in_query_does_not_raise_byteswarning— same with a bytes collection name in the command; asserts the span description containstest_collection, notb'test_collection'.Verified locally (py3.12, pymongo 4.18.1, mockupdb):
b'...'in description) and pass with the fix.pytest tests/integrations/pymongo/→ 55 passed (51 existing + 4 new), also underpython -bwith 0 BytesWarning lines in output.ruff format/ruff checkclean.Per the discussion in the issue (decode vs. repr): this goes with decoding, since the
b'...'form was clearly not intended for span data.Fixes #4782