mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-140826: Compare winreg.HKEYType by the internal handle value (GH-140843)
This commit is contained in:
parent
349de57839
commit
248ce9fa8c
4 changed files with 65 additions and 6 deletions
|
|
@ -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
|
will print ``Yes`` if the handle is currently valid (has not been closed or
|
||||||
detached).
|
detached).
|
||||||
|
|
||||||
The object also support comparison semantics, so handle objects will compare
|
The object also support equality comparison semantics, so handle objects will
|
||||||
true if they both reference the same underlying Windows handle value.
|
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
|
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
|
: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.
|
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 @@ def _test_named_args(self, key, sub_key):
|
||||||
access=KEY_ALL_ACCESS) as okey:
|
access=KEY_ALL_ACCESS) as okey:
|
||||||
self.assertTrue(okey.handle != 0)
|
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):
|
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);
|
return PyUnicode_FromFormat("<PyHKEY:%p>", pyhkey->hkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static PyObject *
|
||||||
PyHKEY_compareFunc(PyObject *ob1, PyObject *ob2)
|
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 *pyhkey1 = (PyHKEYObject *)ob1;
|
||||||
PyHKEYObject *pyhkey2 = (PyHKEYObject *)ob2;
|
PyHKEYObject *pyhkey2 = (PyHKEYObject *)ob2;
|
||||||
return pyhkey1 == pyhkey2 ? 0 :
|
HKEY hkey1 = pyhkey1->hkey;
|
||||||
(pyhkey1 < pyhkey2 ? -1 : 1);
|
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
|
static Py_hash_t
|
||||||
|
|
@ -365,6 +390,7 @@ static PyType_Slot pyhkey_type_slots[] = {
|
||||||
{Py_tp_traverse, _PyObject_VisitType},
|
{Py_tp_traverse, _PyObject_VisitType},
|
||||||
{Py_tp_hash, PyHKEY_hashFunc},
|
{Py_tp_hash, PyHKEY_hashFunc},
|
||||||
{Py_tp_str, PyHKEY_strFunc},
|
{Py_tp_str, PyHKEY_strFunc},
|
||||||
|
{Py_tp_richcompare, PyHKEY_richcompare},
|
||||||
|
|
||||||
// Number protocol
|
// Number protocol
|
||||||
{Py_nb_add, PyHKEY_binaryFailureFunc},
|
{Py_nb_add, PyHKEY_binaryFailureFunc},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue