Support UUID representation
As of pymongo v4+, it should error if used with default representation (Unspecified).
We could implement a first feature that accepts custom representation, and only fails (NotImplementedError) if writing/reading/comparing in different uuid representations for the same server. Otherwise if it's not Unspecified, we could handle UUID the same way we did before pymongo v4.
Hello, I'm bumping this as I believe not being able to specify UUID representation w/ mongomock is the reason for my tests to be breaking with pymongo v4.
I tried sanity checking this by making some DB queries, updates, and additions, and was successful. I am currently using mongoengine v0.24.0 which falls back to PYTHON_LEGACY, which is presumably why it works. I am only failing my unit tests.
Here is a stack trace from a breaking test, which leads me to believe that mongomock is the culprit:
lib/mongo/mongo_nodes.py:188: in save
return super().save(*args, **kwargs)
../../../../.local/share/virtualenvs/services-5Tycw3tD/lib/python3.9/site-packages/mongoengine/document.py:416: in save
object_id = self._save_create(doc, force_insert, write_concern)
../../../../.local/share/virtualenvs/services-5Tycw3tD/lib/python3.9/site-packages/mongoengine/document.py:481: in _save_create
object_id = wc_collection.insert_one(doc).inserted_id
../../../../.local/share/virtualenvs/services-5Tycw3tD/lib/python3.9/site-packages/mongomock/collection.py:463: in insert_one
return InsertOneResult(self._insert(document, session), acknowledged=True)
../../../../.local/share/virtualenvs/services-5Tycw3tD/lib/python3.9/site-packages/mongomock/collection.py:514: in _insert
BSON.encode(data, check_keys=True)
../../../../.local/share/virtualenvs/services-5Tycw3tD/lib/python3.9/site-packages/bson/__init__.py:1150: in encode
return cls(encode(document, check_keys, codec_options))
../../../../.local/share/virtualenvs/services-5Tycw3tD/lib/python3.9/site-packages/bson/__init__.py:871: in encode
return _dict_to_bson(document, check_keys, codec_options)
Can someone confirm?
pymongo 4.0+ requires you to set uuidRepresentation along with other options on client initialization. This is not supported in mongomock and breaks unittests that once relied on the legacy behavior of uuidRepresentation 3 (pythonLegacy).
This should be added along side other kwarg options such as 'tzinfo' and 'tz_aware'.
Poking around I was able to make it work by updating collection.py to pass codec_options when it calls bson.encode. Also had to update the code in the chain of calls that initialize the codec_options for the connection.
@elanou Is this similar to the hack you did?
https://github.com/joshuashaffer/mongomock-uuid-pymongo4/commit/64a5551629bbf2506004eac47ce27daf54d094fc
https://github.com/joshuashaffer/mongomock-uuid-pymongo4/commit/5944358bdc3577f5515dcbfd689728ca9a4834b4
Need to propigate codec_options in a few more places...
Seeing this open for some time and not knowing when the fixes will be merged, here is another suggestion I use, so I can continue using the released version.
import unittest.mock as mock
from uuid import UUID
from bson.binary import Binary, UuidRepresentation, UUID_SUBTYPE
def side_effect_mongo_mock_from_uuid(uuid: UUID, uuid_representation = UuidRepresentation.STANDARD):
"""Override (Mock) the bson.binary.Binary.from_uuid function to work for mongomock
Code is copy pasted from the original function,
but `uuid_representation` is ignored and only code parts as if
uuid_representation == UuidRepresentation.STANDARD are used
"""
if not isinstance(uuid, UUID):
raise TypeError("uuid must be an instance of uuid.UUID")
subtype = UUID_SUBTYPE
payload = uuid.bytes
return Binary(payload, subtype)
@pytest.fixture()
def mongo_uuid(monkeypatch):
with mock.patch.object(Binary, 'from_uuid', side_effect=side_effect_mongo_mock_from_uuid):
yield
Probably the same is requried for the as_uuid function
If using this, be careful as other errors may not be noticed by the test. e.g. uuid_representation having an invalid value is never checked here.