Skip to content

Commit 7a67270

Browse files
committed
PYTHON-2680 Make breaking changes to DBRef BSON+JSON encoding/decoding TODO: C extensions
PYTHON-2841 resync bson corpus tests
1 parent 2170401 commit 7a67270

File tree

4 files changed

+8
-12
lines changed

4 files changed

+8
-12
lines changed

bson/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ def _get_object(data, view, position, obj_end, opts, dummy):
202202
obj = _elements_to_dict(data, view, position + 4, end, opts)
203203

204204
position += obj_size
205-
if "$ref" in obj:
205+
# If DBRef validation fails, return a normal doc.
206+
if isinstance(obj.get('$ref'), str) and "$id" in obj and isinstance(obj.get('$db'), (str, type(None))):
206207
return (DBRef(obj.pop("$ref"), obj.pop("$id", None),
207208
obj.pop("$db", None), obj), position)
208209
return obj, position

bson/json_util.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,6 @@
121121
"x": re.X,
122122
}
123123

124-
# Dollar-prefixed keys which may appear in DBRefs.
125-
_DBREF_KEYS = frozenset(['$id', '$ref', '$db'])
126-
127124

128125
class DatetimeRepresentation:
129126
LEGACY = 0
@@ -463,7 +460,7 @@ def object_pairs_hook(pairs, json_options=DEFAULT_JSON_OPTIONS):
463460
def object_hook(dct, json_options=DEFAULT_JSON_OPTIONS):
464461
if "$oid" in dct:
465462
return _parse_canonical_oid(dct)
466-
if "$ref" in dct:
463+
if isinstance(dct.get('$ref'), str) and "$id" in dct and isinstance(dct.get('$db'), (str, type(None))):
467464
return _parse_canonical_dbref(dct)
468465
if "$date" in dct:
469466
return _parse_canonical_datetime(dct, json_options)
@@ -676,10 +673,6 @@ def _parse_canonical_regex(doc):
676673

677674
def _parse_canonical_dbref(doc):
678675
"""Decode a JSON DBRef to bson.dbref.DBRef."""
679-
for key in doc:
680-
if key.startswith('$') and key not in _DBREF_KEYS:
681-
# Other keys start with $, so dct cannot be parsed as a DBRef.
682-
return doc
683676
return DBRef(doc.pop('$ref'), doc.pop('$id'),
684677
database=doc.pop('$db', None), **doc)
685678

test/bson_corpus/dbref.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
{
2626
"description": "Document with key names similar to those of a DBRef",
2727
"canonical_bson": "3e0000000224726566000c0000006e6f742d612d646272656600072469640058921b3e6e32ab156a22b59e022462616e616e6100050000007065656c0000",
28-
"canonical_extjson": "{\"$ref\": \"not-a-dbref\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$banana\": \"peel\"}"
28+
"canonical_extjson": "{\"$ref\": \"not-a-dbref\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$banana\": \"peel\"}",
29+
"lossy": true
2930
},
3031
{
3132
"description": "DBRef with additional dollar-prefixed and dotted fields",

test/test_bson_corpus.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ def run_test(self):
136136
# Make sure we can parse the legacy (default) JSON format.
137137
legacy_json = json_util.dumps(
138138
decoded_bson, json_options=json_util.LEGACY_JSON_OPTIONS)
139-
self.assertEqual(decode_extjson(legacy_json), decoded_bson)
139+
self.assertEqual(
140+
decode_extjson(legacy_json), decoded_bson, description)
140141

141142
if deprecated:
142143
if 'converted_bson' in valid_case:
@@ -158,7 +159,7 @@ def run_test(self):
158159
if not (sys.platform.startswith("java") and
159160
description == 'NaN with payload'):
160161
# Test round-tripping canonical bson.
161-
self.assertEqual(encode_bson(decoded_bson), cB)
162+
self.assertEqual(encode_bson(decoded_bson), cB, description)
162163
self.assertJsonEqual(encode_extjson(decoded_bson), cEJ)
163164

164165
# Test round-tripping canonical extended json.

0 commit comments

Comments
 (0)