From ec9d95413c2bc993d8cf0cd7fa7fbd83daf862b8 Mon Sep 17 00:00:00 2001 From: Jeffrey 'Alex' Clark Date: Wed, 18 Mar 2026 17:46:23 -0400 Subject: [PATCH] PYTHON-5757 Deprecate Python 2 methods in SON (#2732) --- bson/son.py | 16 ++++++++++++++++ doc/changelog.rst | 5 +++++ test/test_son.py | 4 +--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/bson/son.py b/bson/son.py index 8fd4f95cd..ccb6bdb27 100644 --- a/bson/son.py +++ b/bson/son.py @@ -22,6 +22,7 @@ from __future__ import annotations import copy import re +import warnings from collections.abc import Mapping as _Mapping from typing import ( Any, @@ -99,13 +100,28 @@ class SON(Dict[_Key, _Value]): yield from self.__keys def has_key(self, key: _Key) -> bool: + warnings.warn( + "SON.has_key() is deprecated, use the in operator instead", + DeprecationWarning, + stacklevel=2, + ) return key in self.__keys def iterkeys(self) -> Iterator[_Key]: + warnings.warn( + "SON.iterkeys() is deprecated, use the keys() method instead", + DeprecationWarning, + stacklevel=2, + ) return self.__iter__() # fourth level uses definitions from lower levels def itervalues(self) -> Iterator[_Value]: + warnings.warn( + "SON.itervalues() is deprecated, use the values() method instead", + DeprecationWarning, + stacklevel=2, + ) for _, v in self.items(): yield v diff --git a/doc/changelog.rst b/doc/changelog.rst index f38709203..23d5b2fc9 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -6,6 +6,11 @@ Changes in Version 4.17.0 (2026/XX/XX) PyMongo 4.17 brings a number of changes including: +- ``has_key``, ``iterkeys`` and ``itervalues`` in :class:`bson.son.SON` have + been deprecated and will be removed in PyMongo 5.0. These methods were + deprecated in favor of the standard dictionary containment operator ``in`` + and the ``keys()`` and ``values()`` methods, respectively. + - Added the :meth:`~pymongo.asynchronous.client_session.AsyncClientSession.bind` and :meth:`~pymongo.client_session.ClientSession.bind` methods that allow users to bind a session to all database operations within the scope of a context manager instead of having to explicitly pass the session to each individual operation. See for examples and more information. diff --git a/test/test_son.py b/test/test_son.py index 36a683488..3d2069a4c 100644 --- a/test/test_son.py +++ b/test/test_son.py @@ -145,13 +145,11 @@ class TestSON(unittest.TestCase): self.assertEqual(ele * 100, test_son[ele]) def test_contains_has(self): - """has_key and __contains__""" + """Test key membership via 'in' and __contains__.""" test_son = SON([(1, 100), (2, 200), (3, 300)]) self.assertIn(1, test_son) self.assertIn(2, test_son, "in failed") self.assertNotIn(22, test_son, "in succeeded when it shouldn't") - self.assertTrue(test_son.has_key(2), "has_key failed") - self.assertFalse(test_son.has_key(22), "has_key succeeded when it shouldn't") def test_clears(self): """Test clear()"""