Skip to content

Commit

Permalink
gh-87995: Make MappingProxyType hashable (GH-94252)
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiy-storchaka authored Jun 28, 2022
1 parent 71d5299 commit efdc9d6
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 1 deletion.
6 changes: 6 additions & 0 deletions Doc/library/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,12 @@ Standard names are defined for the following types:

.. versionadded:: 3.9

.. describe:: hash(proxy)

Return a hash of the underlying mapping.

.. versionadded:: 3.12


Additional Utility Classes and Functions
----------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ New Features
Other Language Changes
======================

* :class:`types.MappingProxyType` instances are now hashable if the underlying
mapping is hashable.
(Contributed by Serhiy Storchaka in :gh:`87995`.)


New Modules
Expand Down
10 changes: 10 additions & 0 deletions Lib/test/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,16 @@ def test_union(self):
self.assertDictEqual(mapping, {'a': 0, 'b': 1, 'c': 2})
self.assertDictEqual(other, {'c': 3, 'p': 0})

def test_hash(self):
class HashableDict(dict):
def __hash__(self):
return 3844817361
view = self.mappingproxy({'a': 1, 'b': 2})
self.assertRaises(TypeError, hash, view)
mapping = HashableDict({'a': 1, 'b': 2})
view = self.mappingproxy(mapping)
self.assertEqual(hash(view), hash(mapping))


class ClassCreationTests(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:class:`types.MappingProxyType` instances are now hashable if the underlying
mapping is hashable.
8 changes: 7 additions & 1 deletion Objects/descrobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,12 @@ mappingproxy_getiter(mappingproxyobject *pp)
return PyObject_GetIter(pp->mapping);
}

static Py_hash_t
mappingproxy_hash(mappingproxyobject *pp)
{
return PyObject_Hash(pp->mapping);
}

static PyObject *
mappingproxy_str(mappingproxyobject *pp)
{
Expand Down Expand Up @@ -1901,7 +1907,7 @@ PyTypeObject PyDictProxy_Type = {
&mappingproxy_as_number, /* tp_as_number */
&mappingproxy_as_sequence, /* tp_as_sequence */
&mappingproxy_as_mapping, /* tp_as_mapping */
0, /* tp_hash */
(hashfunc)mappingproxy_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)mappingproxy_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
Expand Down

0 comments on commit efdc9d6

Please sign in to comment.