From 9bcbc1d5563eb776a08e936eba04914bd5206e4a Mon Sep 17 00:00:00 2001 From: John Kirkham Date: Tue, 12 Feb 2019 01:19:57 -0500 Subject: [PATCH 1/2] Drop binary_type cast in MongoDBStore.__getitem__ --- zarr/storage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zarr/storage.py b/zarr/storage.py index d71ee3a18a..3961d8b857 100644 --- a/zarr/storage.py +++ b/zarr/storage.py @@ -2147,7 +2147,7 @@ def __getitem__(self, key): if doc is None: raise KeyError(key) else: - return binary_type(doc[self._value]) + return doc[self._value] def __setitem__(self, key, value): value = ensure_bytes(value) From efa3ee918a5ac510e98ebd28c0404b773c33047a Mon Sep 17 00:00:00 2001 From: John Kirkham Date: Wed, 13 Feb 2019 01:36:59 -0500 Subject: [PATCH 2/2] Coerce PyMongo values to `binary_type` on Python 2 On both Python 2 and Python 3, PyMongo converts `binary_type` (i.e. `bytes`) to BSON type 5 (Binary data) with subtype 0 to store in the MongoDB instance. When reading that data back out, PyMongo handles BSON type 5 (Binary data) with subtype 0 differently depending on the Python version. On Python 2, it creates a `bson.Binary` instance with the data. Normally we would coerce this to a `bytes` object using `ensure_bytes`. However that fails as `bson.Binary` is a subclass of `bytes`. So instead we explicitly force it to `bytes` (i.e. `binary_type`). On Python 3, PyMongo automatically converts the data to `bytes`. Thus we don't need to do anything there. ref: http://api.mongodb.com/python/current/python3.html#id3 ref: http://api.mongodb.com/python/current/api/bson/binary.html#bson.binary.Binary --- zarr/storage.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/zarr/storage.py b/zarr/storage.py index 3961d8b857..656b05acf8 100644 --- a/zarr/storage.py +++ b/zarr/storage.py @@ -2147,7 +2147,15 @@ def __getitem__(self, key): if doc is None: raise KeyError(key) else: - return doc[self._value] + value = doc[self._value] + + # Coerce `bson.Binary` to `bytes` type on Python 2. + # PyMongo handles this conversion for us on Python 3. + # ref: http://api.mongodb.com/python/current/python3.html#id3 + if PY2: # pragma: py3 no cover + value = binary_type(value) + + return value def __setitem__(self, key, value): value = ensure_bytes(value)