https://github.com/python/cpython/commit/248ce9fa8c7a1ed1912e0db31172c8cd2c298b37
commit: 248ce9fa8c7a1ed1912e0db31172c8cd2c298b37
branch: main
author: AN Long <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-11-03T10:14:22+02:00
summary:
gh-140826: Compare winreg.HKEYType by the internal handle value (GH-140843)
files:
A Misc/NEWS.d/next/Library/2025-11-01-00-34-53.gh-issue-140826.JEDd7U.rst
M Doc/library/winreg.rst
M Lib/test/test_winreg.py
M PC/winreg.c
diff --git a/Doc/library/winreg.rst b/Doc/library/winreg.rst
index 83c49876d267db..df8fb83a018997 100644
--- a/Doc/library/winreg.rst
+++ b/Doc/library/winreg.rst
@@ -771,8 +771,9 @@ Handle objects provide semantics for
:meth:`~object.__bool__` -- thus ::
will print ``Yes`` if the handle is currently valid (has not been closed or
detached).
-The object also support comparison semantics, so handle objects will compare
-true if they both reference the same underlying Windows handle value.
+The object also support equality comparison semantics, so handle objects will
+compare equal if they both reference the same underlying Windows handle value.
+Closed handle objects (those with a handle value of zero) always compare equal.
Handle objects can be converted to an integer (e.g., using the built-in
:func:`int` function), in which case the underlying Windows handle value is
@@ -815,3 +816,6 @@ integer handle, and also disconnect the Windows handle from
the handle object.
will automatically close *key* when control leaves the :keyword:`with`
block.
+.. versionchanged:: next
+ Handle objects are now compared by their underlying Windows handle value
+ instead of object identity for equality comparisons.
diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py
index 6f2a6ac900be82..733d30b3922d35 100644
--- a/Lib/test/test_winreg.py
+++ b/Lib/test/test_winreg.py
@@ -209,6 +209,33 @@ def _test_named_args(self, key, sub_key):
access=KEY_ALL_ACCESS) as okey:
self.assertTrue(okey.handle != 0)
+ def test_hkey_comparison(self):
+ """Test HKEY comparison by handle value rather than object identity."""
+ key1 = OpenKey(HKEY_CURRENT_USER, None)
+ key2 = OpenKey(HKEY_CURRENT_USER, None)
+ key3 = OpenKey(HKEY_LOCAL_MACHINE, None)
+
+ self.addCleanup(CloseKey, key1)
+ self.addCleanup(CloseKey, key2)
+ self.addCleanup(CloseKey, key3)
+
+ self.assertEqual(key1.handle, key2.handle)
+ self.assertTrue(key1 == key2)
+ self.assertFalse(key1 != key2)
+
+ self.assertTrue(key1 != key3)
+ self.assertFalse(key1 == key3)
+
+ # Closed keys should be equal (all have handle=0)
+ CloseKey(key1)
+ CloseKey(key2)
+ CloseKey(key3)
+
+ self.assertEqual(key1.handle, 0)
+ self.assertEqual(key2.handle, 0)
+ self.assertEqual(key3.handle, 0)
+ self.assertEqual(key2, key3)
+
class LocalWinregTests(BaseWinregTests):
diff --git
a/Misc/NEWS.d/next/Library/2025-11-01-00-34-53.gh-issue-140826.JEDd7U.rst
b/Misc/NEWS.d/next/Library/2025-11-01-00-34-53.gh-issue-140826.JEDd7U.rst
new file mode 100644
index 00000000000000..875d15f2f8917c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-11-01-00-34-53.gh-issue-140826.JEDd7U.rst
@@ -0,0 +1,2 @@
+Now :class:`!winreg.HKEYType` objects are compared by their underlying Windows
+registry handle value instead of their object identity.
diff --git a/PC/winreg.c b/PC/winreg.c
index 8633f29670e263..c7bc74728f1ff9 100644
--- a/PC/winreg.c
+++ b/PC/winreg.c
@@ -181,13 +181,38 @@ PyHKEY_strFunc(PyObject *ob)
return PyUnicode_FromFormat("<PyHKEY:%p>", pyhkey->hkey);
}
-static int
-PyHKEY_compareFunc(PyObject *ob1, PyObject *ob2)
+static PyObject *
+PyHKEY_richcompare(PyObject *ob1, PyObject *ob2, int op)
{
+ /* Both objects must be PyHKEY objects from the same module */
+ if (Py_TYPE(ob1) != Py_TYPE(ob2)) {
+ Py_RETURN_NOTIMPLEMENTED;
+ }
+
PyHKEYObject *pyhkey1 = (PyHKEYObject *)ob1;
PyHKEYObject *pyhkey2 = (PyHKEYObject *)ob2;
- return pyhkey1 == pyhkey2 ? 0 :
- (pyhkey1 < pyhkey2 ? -1 : 1);
+ HKEY hkey1 = pyhkey1->hkey;
+ HKEY hkey2 = pyhkey2->hkey;
+ int result;
+
+ switch (op) {
+ case Py_EQ:
+ result = (hkey1 == hkey2);
+ break;
+ case Py_NE:
+ result = (hkey1 != hkey2);
+ break;
+ default:
+ /* Only support equality comparisons, not ordering */
+ Py_RETURN_NOTIMPLEMENTED;
+ }
+
+ if (result) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
}
static Py_hash_t
@@ -365,6 +390,7 @@ static PyType_Slot pyhkey_type_slots[] = {
{Py_tp_traverse, _PyObject_VisitType},
{Py_tp_hash, PyHKEY_hashFunc},
{Py_tp_str, PyHKEY_strFunc},
+ {Py_tp_richcompare, PyHKEY_richcompare},
// Number protocol
{Py_nb_add, PyHKEY_binaryFailureFunc},
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]