diff --git a/bson/__init__.py b/bson/__init__.py index e473166a4..298112d73 100644 --- a/bson/__init__.py +++ b/bson/__init__.py @@ -70,7 +70,7 @@ from collections import abc as _abc from bson.binary import (Binary, UuidRepresentation, ALL_UUID_SUBTYPES, OLD_UUID_SUBTYPE, JAVA_LEGACY, CSHARP_LEGACY, - UUIDLegacy, UUID_SUBTYPE) + UUID_SUBTYPE) from bson.code import Code from bson.codec_options import ( CodecOptions, DEFAULT_CODEC_OPTIONS, _raw_document_class) @@ -707,7 +707,6 @@ _ENCODERS = { RE_TYPE: _encode_regex, SON: _encode_mapping, Timestamp: _encode_timestamp, - UUIDLegacy: _encode_binary, Decimal128: _encode_decimal128, # Special case. This will never be looked up directly. _abc.Mapping: _encode_mapping, diff --git a/bson/binary.py b/bson/binary.py index 7759e9709..7110fede2 100644 --- a/bson/binary.py +++ b/bson/binary.py @@ -337,92 +337,3 @@ class Binary(bytes): def __repr__(self): return "Binary(%s, %s)" % (bytes.__repr__(self), self.__subtype) - - -class UUIDLegacy(Binary): - """**DEPRECATED** - UUID wrapper to support working with UUIDs stored as - PYTHON_LEGACY. - - .. note:: This class has been deprecated and will be removed in - PyMongo 4.0. Use :meth:`~bson.binary.Binary.from_uuid` and - :meth:`~bson.binary.Binary.as_uuid` with the appropriate - :class:`~bson.binary.UuidRepresentation` to handle legacy-formatted - UUIDs instead.:: - - from bson import Binary, UUIDLegacy, UuidRepresentation - import uuid - - my_uuid = uuid.uuid4() - legacy_uuid = UUIDLegacy(my_uuid) - binary_uuid = Binary.from_uuid( - my_uuid, UuidRepresentation.PYTHON_LEGACY) - - assert legacy_uuid == binary_uuid - assert legacy_uuid.uuid == binary_uuid.as_uuid( - UuidRepresentation.PYTHON_LEGACY) - - .. doctest:: - - >>> import uuid - >>> from bson.binary import Binary, UUIDLegacy, STANDARD - >>> from bson.codec_options import CodecOptions - >>> my_uuid = uuid.uuid4() - >>> coll = db.get_collection('test', - ... CodecOptions(uuid_representation=STANDARD)) - >>> coll.insert_one({'uuid': Binary(my_uuid.bytes, 3)}).inserted_id - ObjectId('...') - >>> coll.count_documents({'uuid': my_uuid}) - 0 - >>> coll.count_documents({'uuid': UUIDLegacy(my_uuid)}) - 1 - >>> coll.find({'uuid': UUIDLegacy(my_uuid)})[0]['uuid'] - UUID('...') - >>> - >>> # Convert from subtype 3 to subtype 4 - >>> doc = coll.find_one({'uuid': UUIDLegacy(my_uuid)}) - >>> coll.replace_one({"_id": doc["_id"]}, doc).matched_count - 1 - >>> coll.count_documents({'uuid': UUIDLegacy(my_uuid)}) - 0 - >>> coll.count_documents({'uuid': {'$in': [UUIDLegacy(my_uuid), my_uuid]}}) - 1 - >>> coll.find_one({'uuid': my_uuid})['uuid'] - UUID('...') - - Raises :exc:`TypeError` if `obj` is not an instance of :class:`~uuid.UUID`. - - :Parameters: - - `obj`: An instance of :class:`~uuid.UUID`. - - .. versionchanged:: 3.11 - Deprecated. The same functionality can be replicated using the - :meth:`~Binary.from_uuid` and :meth:`~Binary.to_uuid` methods with - :data:`~UuidRepresentation.PYTHON_LEGACY`. - .. versionadded:: 2.1 - """ - - def __new__(cls, obj): - warn( - "The UUIDLegacy class has been deprecated and will be removed " - "in PyMongo 4.0. Use the Binary.from_uuid() and Binary.to_uuid() " - "with the appropriate UuidRepresentation to handle " - "legacy-formatted UUIDs instead.", - DeprecationWarning, stacklevel=2) - if not isinstance(obj, UUID): - raise TypeError("obj must be an instance of uuid.UUID") - self = Binary.__new__(cls, obj.bytes, OLD_UUID_SUBTYPE) - self.__uuid = obj - return self - - def __getnewargs__(self): - # Support copy and deepcopy - return (self.__uuid,) - - @property - def uuid(self): - """UUID instance wrapped by this UUIDLegacy instance. - """ - return self.__uuid - - def __repr__(self): - return "UUIDLegacy('%s')" % self.__uuid diff --git a/bson/codec_options.py b/bson/codec_options.py index 1a853d1fc..9ce772427 100644 --- a/bson/codec_options.py +++ b/bson/codec_options.py @@ -207,8 +207,8 @@ class CodecOptions(_options_base): See :doc:`/examples/datetimes` for examples using the `tz_aware` and `tzinfo` options. - See :class:`~bson.binary.UUIDLegacy` for examples using the - `uuid_representation` option. + See :doc:`examples/uuid` for examples using the `uuid_representation` + option. :Parameters: - `document_class`: BSON documents returned in queries will be decoded diff --git a/doc/api/bson/binary.rst b/doc/api/bson/binary.rst index ab4d599f8..a754d43d5 100644 --- a/doc/api/bson/binary.rst +++ b/doc/api/bson/binary.rst @@ -22,7 +22,3 @@ .. autoclass:: Binary(data, subtype=BINARY_SUBTYPE) :members: :show-inheritance: - - .. autoclass:: UUIDLegacy(obj) - :members: - :show-inheritance: diff --git a/doc/changelog.rst b/doc/changelog.rst index 189e33e00..d97c8dbe6 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -86,6 +86,7 @@ Breaking Changes in 4.0 - Removed :exc:`pymongo.errors.NotMasterError`. Use :exc:`pymongo.errors.NotPrimaryError` instead. - Removed :attr:`pymongo.GEOHAYSTACK`. +- Removed :class:`bson.binary.UUIDLegacy`. - The "tls" install extra is no longer necessary or supported and will be ignored by pip. @@ -307,6 +308,8 @@ Highlights include: ``MongoClient(uuidRepresentation='unspecified')`` which will become the default UUID representation starting in PyMongo 4.0. See :ref:`handling-uuid-data-example` for details. +- New methods :meth:`bson.binary.Binary.from_uuid` and + :meth:`bson.binary.Binary.as_uuid`. - Added the ``background`` parameter to :meth:`pymongo.database.Database.validate_collection`. For a description of this parameter see the MongoDB documentation for the `validate command`_. @@ -342,6 +345,8 @@ Deprecations: - Deprecated :attr:`pymongo.mongo_client.MongoClient.is_locked`. Use :meth:`~pymongo.database.Database.command` to run the ``currentOp`` command instead. See the documentation for more information. +- Deprecated :class:`bson.binary.UUIDLegacy`. Use + :meth:`bson.binary.Binary.from_uuid` instead. Unavoidable breaking changes: diff --git a/doc/migrate-to-pymongo4.rst b/doc/migrate-to-pymongo4.rst index 7c741e8cb..6b84c7fcb 100644 --- a/doc/migrate-to-pymongo4.rst +++ b/doc/migrate-to-pymongo4.rst @@ -499,6 +499,20 @@ Removed :attr:`pymongo.GEOHAYSTACK`. Replace with "geoHaystack" or create a 2d index and use $geoNear or $geoWithin instead. See https://dochub.mongodb.org/core/4.4-deprecate-geoHaystack. +UUIDLegacy is removed +--------------------- + +Removed :class:`bson.binary.UUIDLegacy`. Use +:meth:`bson.binary.Binary.from_uuid` instead. Code like this:: + + uu = uuid.uuid4() + uuid_legacy = UUIDLegacy(uu) + +can be changed to this:: + + uu = uuid.uuid4() + uuid_legacy = Binary.from_uuid(uu, PYTHON_LEGACY) + Removed features with no migration path --------------------------------------- diff --git a/test/test_binary.py b/test/test_binary.py index 8018c74b5..440c04667 100644 --- a/test/test_binary.py +++ b/test/test_binary.py @@ -287,9 +287,7 @@ class TestBinary(unittest.TestCase): CSHARP_LEGACY) @client_context.require_connection - @ignore_deprecations def test_uuid_queries(self): - db = client_context.client.pymongo_test coll = db.test coll.drop() @@ -298,29 +296,23 @@ class TestBinary(unittest.TestCase): coll.insert_one({'uuid': Binary(uu.bytes, 3)}) self.assertEqual(1, coll.count_documents({})) - # Test UUIDLegacy queries. + # Test regular UUID queries (using subtype 4). coll = db.get_collection( "test", CodecOptions( uuid_representation=UuidRepresentation.STANDARD)) - self.assertEqual(0, coll.find({'uuid': uu}).count()) - cur = coll.find({'uuid': UUIDLegacy(uu)}) - self.assertEqual(1, cur.count()) - retrieved = next(cur) - self.assertEqual(uu, retrieved['uuid']) - - # Test regular UUID queries (using subtype 4). + self.assertEqual(0, coll.count_documents({'uuid': uu})) coll.insert_one({'uuid': uu}) self.assertEqual(2, coll.count_documents({})) - cur = coll.find({'uuid': uu}) - self.assertEqual(1, cur.count()) - retrieved = next(cur) - self.assertEqual(uu, retrieved['uuid']) + docs = list(coll.find({'uuid': uu})) + self.assertEqual(1, len(docs)) + self.assertEqual(uu, docs[0]['uuid']) # Test both. - predicate = {'uuid': {'$in': [uu, UUIDLegacy(uu)]}} + uu_legacy = Binary.from_uuid(uu, UuidRepresentation.PYTHON_LEGACY) + predicate = {'uuid': {'$in': [uu, uu_legacy]}} self.assertEqual(2, coll.count_documents(predicate)) - cur = coll.find(predicate) - self.assertEqual(2, cur.count()) + docs = list(coll.find(predicate)) + self.assertEqual(2, len(docs)) coll.drop() def test_pickle(self): @@ -338,7 +330,7 @@ class TestBinary(unittest.TestCase): self.assertEqual(b1, pickle.loads(pickle.dumps(b1, proto))) uu = uuid.uuid4() - uul = UUIDLegacy(uu) + uul = Binary.from_uuid(uu, UuidRepresentation.PYTHON_LEGACY) self.assertEqual(uul, copy.copy(uul)) self.assertEqual(uul, copy.deepcopy(uul)) diff --git a/test/test_bson.py b/test/test_bson.py index ccae6fcd6..ee30c8948 100644 --- a/test/test_bson.py +++ b/test/test_bson.py @@ -41,7 +41,7 @@ from bson import (BSON, EPOCH_AWARE, is_valid, Regex) -from bson.binary import Binary, UUIDLegacy +from bson.binary import Binary, UuidRepresentation from bson.code import Code from bson.codec_options import CodecOptions from bson.int64 import Int64 @@ -646,14 +646,12 @@ class TestBSON(unittest.TestCase): self.assertNotEqual(uuid.uuid4(), transformed_id) def test_uuid_legacy(self): - id = uuid.uuid4() - legacy = UUIDLegacy(id) + legacy = Binary.from_uuid(id, UuidRepresentation.PYTHON_LEGACY) self.assertEqual(3, legacy.subtype) transformed = decode(encode({"uuid": legacy}))["uuid"] self.assertTrue(isinstance(transformed, uuid.UUID)) self.assertEqual(id, transformed) - self.assertNotEqual(UUIDLegacy(uuid.uuid4()), UUIDLegacy(transformed)) # The C extension was segfaulting on unicode RegExs, so we have this test # that doesn't really test anything but the lack of a segfault. diff --git a/test/test_common.py b/test/test_common.py index 5a35fd8bb..896df50e5 100644 --- a/test/test_common.py +++ b/test/test_common.py @@ -19,7 +19,7 @@ import uuid sys.path[0:0] = [""] -from bson.binary import UUIDLegacy, PYTHON_LEGACY, STANDARD +from bson.binary import Binary, PYTHON_LEGACY, STANDARD from bson.code import Code from bson.codec_options import CodecOptions from bson.objectid import ObjectId @@ -53,7 +53,8 @@ class TestCommon(IntegrationTest): "uuid", CodecOptions(uuid_representation=STANDARD)) self.assertEqual(STANDARD, coll.codec_options.uuid_representation) self.assertEqual(None, coll.find_one({'uu': uu})) - self.assertEqual(uu, coll.find_one({'uu': UUIDLegacy(uu)})['uu']) + uul = Binary.from_uuid(uu, PYTHON_LEGACY) + self.assertEqual(uu, coll.find_one({'uu': uul})['uu']) # Test count_documents self.assertEqual(0, coll.count_documents({'uu': uu})) @@ -104,7 +105,7 @@ class TestCommon(IntegrationTest): self.assertEqual(6, self.db.command( 'findAndModify', 'uuid', update={'$set': {'i': 7}}, - query={'_id': UUIDLegacy(uu)})['value']['i']) + query={'_id': Binary.from_uuid(uu, PYTHON_LEGACY)})['value']['i']) # Test (inline)_map_reduce coll.drop()