Skip to content

MappingProxyType cannot hash a hashable underlying mapping #87995

Closed
@andy-maier

Description

@andy-maier
Mannequin
BPO 43829
Nosy @rhettinger, @serhiy-storchaka, @andy-maier

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2021-04-13.08:25:32.893>
labels = ['type-bug', 'library', '3.10']
title = 'MappingProxyType cannot hash a hashable underlying mapping'
updated_at = <Date 2021-04-14.07:46:45.086>
user = 'https://github.com/andy-maier'

bugs.python.org fields:

activity = <Date 2021-04-14.07:46:45.086>
actor = 'serhiy.storchaka'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2021-04-13.08:25:32.893>
creator = 'andymaier'
dependencies = []
files = []
hgrepos = []
issue_num = 43829
keywords = []
message_count = 4.0
messages = ['390936', '391028', '391038', '391041']
nosy_count = 3.0
nosy_names = ['rhettinger', 'serhiy.storchaka', 'andymaier']
pr_nums = []
priority = 'low'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue43829'
versions = ['Python 3.10']

Activity

andy-maier

andy-maier commented on Apr 13, 2021

@andy-maier
MannequinAuthor

Objects of MappingProxyType do expose a __hash__() method, but if the underlying mapping is hashable, it still does not support hashing it.

Example:

Content of mp_hash.py:

------
#!/usr/bin/env python

from nocasedict import NocaseDict, HashableMixin
from types import MappingProxyType

class HashableDict(HashableMixin, NocaseDict):
    """A hashable dictionary"""
    pass

hd = HashableDict({'a': 1, 'b': 2})
print("hash(hd): {}".format(hash(hd)))

mp = MappingProxyType(hd)
print("hash(mp): {}".format(hash(mp)))

Running the mp_hash.py script:

hash(hd): 3709951335832776636
Traceback (most recent call last):
  File "/Users/maiera/Projects/Python/cpython/issues/mappingproxy/./mp_hash.py", line 14, in <module>
    print("hash(mp): {}".format(hash(mp)))
TypeError: unhashable type: 'mappingproxy'

There are use cases where a function wants to return an immutable view on an internal dictionary, and the caller of the function should be able to use the returned object like a dictionary, except that it is read-only.

Note there is https://bugs.python.org/issue31209 on the inability to pickle MappingProxyType objects which was closed without adding the capability. That would fall under the same argument.

added
3.9only security fixes
stdlibPython modules in the Lib dir
type-bugAn unexpected behavior, bug, or error
on Apr 13, 2021
rhettinger

rhettinger commented on Apr 14, 2021

@rhettinger
Contributor

Serhiy, what do you think? Would it make sense to pass through the underlying hash? I don't think there is much use for this but don't see any particular reason to block it.

added
3.10only security fixes
and removed
3.9only security fixes
on Apr 14, 2021
serhiy-storchaka

serhiy-storchaka commented on Apr 14, 2021

@serhiy-storchaka
Member

Perhaps MappingProxyType is unhashable by accident. It implements __eq__, and it makes it unhashable by default. And nobody made request for this feature before. I think that implementing __hash__ would not make anything wrong.

serhiy-storchaka

serhiy-storchaka commented on Apr 14, 2021

@serhiy-storchaka
Member

But there is an issue with comparison implementation in MappingProxyType (see bpo-43838). Resolving that issue can affect the decision about hashability.

There should be always true the following predicate: if x == y then hash(x) == hash(y).

transferred this issue fromon Apr 10, 2022
vbrozik

vbrozik commented on Jun 21, 2022

@vbrozik

The issue #88004 (bpo-43838) was already closed with reasoning:

... the reason we proxy in the first place is not absolute safety but to make sure
people don’t accidentally update the dict when they intend to update the
class ...

In general, it is hard to completely wall-off instances against deliberate efforts to pry them open

I do not se a reason why not allow the hashing. Recently I needed to collect a set of small unique dict objects. It is a pity that I could not utilize MappingProxyType directly.

added a commit that references this issue on Jun 25, 2022

pythongh-87995: Make MappingProxyType hashable

added a commit that references this issue on Jun 28, 2022

gh-87995: Make MappingProxyType hashable (GH-94252)

efdc9d6
ambv

ambv commented on Jun 28, 2022

@ambv
Contributor

This is now fixed. Thanks, Serhiy! ✨ 🍰 ✨

4 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.10only security fixesstdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @ambv@rhettinger@serhiy-storchaka@matanox@vbrozik

        Issue actions

          MappingProxyType cannot hash a hashable underlying mapping · Issue #87995 · python/cpython