Skip to content

gh-152636: Add a note about frozendict to the types.MappingProxyType#152637

Closed
sobolevn wants to merge 3 commits into
python:mainfrom
sobolevn:issue-152636
Closed

gh-152636: Add a note about frozendict to the types.MappingProxyType#152637
sobolevn wants to merge 3 commits into
python:mainfrom
sobolevn:issue-152636

Conversation

@sobolevn

@sobolevn sobolevn commented Jun 29, 2026

Copy link
Copy Markdown
Member

I didn't know provide links to the exact issue on github, but I can if others think that it is needed.

Refs #152405
Refs #152483

@sobolevn sobolevn added the needs backport to 3.15 pre-release feature fixes, bugs and security fixes label Jun 29, 2026
@bedevere-app bedevere-app Bot added docs Documentation in the Doc dir skip news labels Jun 29, 2026
@github-project-automation github-project-automation Bot moved this to Todo in Docs PRs Jun 29, 2026
@read-the-docs-community

read-the-docs-community Bot commented Jun 29, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33445897 | 📁 Comparing 4da78f7 against main (edcc07d)

  🔍 Preview build  

34 files changed · ± 34 modified

± Modified

@methane

methane commented Jun 30, 2026

Copy link
Copy Markdown
Member

This warning feels redundant to me. MappingProxyType is ultimately just a proxy; it is sometimes used as a substitute for frozendict, but that is not its main purpose. MappingProxyType is not a well-known class, so people will probably find frozendict more easily.

@StanFromIreland

Copy link
Copy Markdown
Member

I agree with Raymond (on issue) and Inada (above), the docs should stay neutral, rather than recommend one over the other. The two types do two different things, claiming either is universally better is false.

Comment thread Doc/library/types.rst Outdated
``MappingProxyType`` can expose its internal mapping
in some rare cases on some versions of Python.
Starting from Python 3.15 it is recommeneded
to use truly immutable :class:`frozendict` instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that a "warning" is justified here, a "note" would be enough.

For the second sentence, maybe only recommend frozendict to "store sensitive information".

@vstinner

vstinner commented Jun 30, 2026

Copy link
Copy Markdown
Member

My concern is that multiple bugs exposing the internal mapping have been fixed so far, but there might be more bugs awaiting. Instead of trying to fix all bugs, I suggested adding a note in MappingProxyType doc explaining that the internal mapping can be leaked, it's not 100% "secure", and using a frozendict avoids these issues.

@vstinner

Copy link
Copy Markdown
Member

I agree with Raymond (on issue) and Inada (above), the docs should stay neutral, rather than recommend one over the other. The two types do two different things, claiming either is universally better is false.

frozendict doesn't replace MappingProxyType in all cases, but it's safer if you want to store sensitive information.

@vstinner

Copy link
Copy Markdown
Member

An example accessing and modifying the internal mapping:

import gc, types
# the internal mapping is not stored in a variable
# to make sure that it cannot be modified
private = types.MappingProxyType({'password': 82349281})
for ref in gc.get_referents(private):
    if isinstance(ref, dict):
        ref['password'] = 123
print(private)

Output:

{'password': 123}

I don't think that we can fix this bug or "vulnerability", the GC must track the MappingProxyType since it can be part of a reference cycle.

@sobolevn sobolevn changed the title gh-152636: Add a note that frozendict is preferable than MappingProxyType gh-152636: Add a note about frozendict to the types.MappingProxyType Jun 30, 2026
@sobolevn

Copy link
Copy Markdown
Member Author

Updated :)
I am using Raymond's wording from #152636 (comment)

For me, it explains the difference perfectly :)

@methane

methane commented Jul 1, 2026

Copy link
Copy Markdown
Member

I still feel that this note is redundant and reduces the S/N ratio of the documentation, but I don't strongly object to it.

@sobolevn

sobolevn commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

this note is redundant and reduces the S/N ratio of the documentation

I asked several Python people from my community, how many of them can explain such difference. Not many of them could :)

So, I think that this is a not really a noise, but an important difference between two stdlib containers that people should be aware of and understand their desired use-case :)

If there are no other objections / specific rephrase ideas, I will merge this PRs in a week or so :)

Comment thread Doc/library/types.rst Outdated
``MappingProxyType`` can expose its internal mapping in some rare cases.

While ``frozendict`` is a concrete container type
that actually holds data that cannot be changed in any way.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can envision people creating issues because the following doesn't hold:

x = {1: [1,2]}
y = frozendict(x)
x[1].append(2)
assert y[1] == [1,2]

I don't know if we make a difference between data in the sense (key, value), namely you can't change the assignment (key) to (value) (in terms of pointers, you don't change that) vs what the value actually is (it's still some "data" inside that frozendict as it's the value of y[1] in my example). But by saying "cannot be changed in any way" is too strong. It may be understood as making a deep-copy of the dict content.

Also, if you start your sentence with While, there should a subject afterwards, e.g, While X, Y. If you want to drop the Y part, I'd say "On the other hand, X".

@methane

methane commented Jul 5, 2026

Copy link
Copy Markdown
Member

I asked several Python people from my community, how many of them can explain such difference. Not many of them could :)

So, I think that this is a not really a noise, but an important difference between two stdlib containers that people should be aware of and understand their desired use-case :)

For the average Python user, I think MappingProxyType is something they have never even seen, and it would not come up as a candidate when they try to choose a container that fits their use case.
In that situation, the fact that the average Python user cannot explain the difference between frozendict and MappingProxyType does not speak to the importance of this note.

This note matters only for Python users who would consider MappingProxyType as a candidate when choosing a container, and who find the difference between MappingProxyType and frozendict hard to understand.
For that user, I think it is almost self-evident that MappingProxyType is a proxy, and that the relationship between dict and frozendict is the same as that between set and frozenset.

Comment thread Doc/library/types.rst
without affecting the underlying container.
``MappingProxyType`` can expose its internal mutable mapping in some rare cases.

On the other hand, ``frozendict`` is a concrete immutable mapping.

@picnixz picnixz Jul 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK both MappingProxyType and frozendict are (immutable) mappings if we consider collections.abc.Mapping. So... I don't know whether there is really a need for that note in the end. "concrete immutable mapping" applies to both of them. I'm sorry for being nitpicky though but I agree with Inada here that this note could be more confusing depending on who reads it.

We already say

   Read-only proxy of a mapping. It provides a dynamic view on the mapping's
   entries, which means that when the mapping changes, the view reflects these
   changes.

I would just say (if I were to change the docs, but that's not even sure)

   Read-only proxy of a mapping. It provides a dynamic view on the mapping's
   entries, which means that when the mapping changes, the view reflects these
   changes.

   Use :class:`frozendict` if you want an immutable shallow copy of a mapping.

@sobolevn

sobolevn commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

Ok then, let's not touch this :)

@sobolevn sobolevn closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting core review docs Documentation in the Doc dir needs backport to 3.15 pre-release feature fixes, bugs and security fixes skip news

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

5 participants