gh-140826: Compare winreg.HKEYType by the internal handle value (GH-140843)
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -209,6 +209,33 @@ class BaseWinregTests(unittest.TestCase):
|
||||
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):
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Now :class:`!winreg.HKEYType` objects are compared by their underlying Windows
|
||||
registry handle value instead of their object identity.
|
||||
34
PC/winreg.c
34
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},
|
||||
|
||||
Reference in New Issue
Block a user