PEP 705: Read-only TypedDict items

I think that was his point, hence the following sentence. But at that point Readable and ReadOnly are essentially equivalent with the only potential difference being how it would synthesize with a type that explicitly defines a __setattr__(self, name: str, val: object) -> None, although for soundness, they either both would need to synthesize to the same or the one without __setattr__ would need to feature an additional restriction of disallowing defining an arbitrary __setattr__ when any attribute is Readable/ReadOnly, however you wanna call it.

So I think the original framing was more accurate if you want a StrictlyReadOnly which can’t be overridden to be writeable. [1]

For nominal types Final may be sufficient, although I’d argue you should still be able to redefine what a StrictlyReadOnly attribute returns on a subclass. For a Protocol Final does not make any sense, so you’d still be lacking the ability to define a Protocol which guarantees an attribute is read only, which you may care about in the free threaded future of Python, so you can with confidence say a value won’t be changed from under your nose by another thread[2].


  1. Although it would have to be __setattr__(self, name: Literal["foo"], val: object) -> Never so T remains covariant ↩︎

  2. Although at that point the definition would have to be even more strict, so the ReadOnly property can’t itself derive from a writeable attribute ↩︎

Yes, I realised after I posted, and edited away my mistake. I miss wikis.

Actually, pyright allows this construct.

I think the thing I’m missing is why you would want a StrictReadOnly annotation at all. Given it can be implemented with a function in a subclass, it provides no guarantee that it will return the same value each time, so really all you’re doing is banning a setattr overload. Why prevent that one specific way for that attribute to be modified in a subclass, but not any other?

I’m mostly playing devil’s advocate. I don’t really have a specific use-case in mind and I don’t think I would personally use a StrictlyReadOnly. I’d likely be content with the lax definition of ReadOnly. But that’s also mostly because we don’t have either definition of ReadOnly to play around with yet, so I haven’t really had an opportunity yet to think that hard about it in real world examples.

ReadOnly is in typing-extensions and pyright (including the new online playground) if you want to try it.

I meant the extended version, that would also be supported in Protocol and nominal types, sorry if I wasn’t very clear about that. I don’t foresee a compelling need for StrictlyReadOnly coming up in TypedDict[1], since there isn’t really a nominal type that’s compatible with a TypedDict, dict literals are a special case. I think it’s somewhat more likely that a use-case will come up with Protocol and ABC.


This seems very ambiguous, since Protocol can have a default implementation. Does Final mean you are setting the value in the Protocol and every implementation needs to use the same value, or can an implementation define its own value as long as it’s also Final? What if you are inheriting from the Protocol, are you still allowed to redefine or is it now forbidden? It looks like pyright allows redefinition if it doesn’t inherit, but it forbids if you inherit, regardless of whether or not the Protocol provided a value for the attribute, this seems inconsistent, because inheriting from a Protocol should be equivalent to not inheriting from it from a type checker’s perspective [2], unless it inherits from Protocol again so it remains a Protocol.

I think I prefer mypy’s interpretation which both disallows not setting a value for a Final attribute and disallows marking a Protocol attribute as Final in the first place.

But we are getting lost in the weeds here, so I’ll stop there.


  1. Apart from being able to guard yourself against accidentally overriding a ReadOnly item with a writeable one in a subclass, but that’s a fairly narrow use-case ↩︎

  2. apart from not requiring it to override methods/attribute with a default implementation ↩︎

This is something that I would like outside of TypedDict. It would solve this problem that I’ve run into a few times.

I would appreciate it if you would consider not limiting it to TypedDict.
I would understand if you want to limit the scope to keep things simple, but if so, it might be worth mentioning that ReadOnly could be extended in a future PEP to solve similar problems outside of TypedDict.

The PEP already says so; see the last sentence in PEP 705 – TypedDict: Read-only items | peps.python.org. I would oppose extending ReadOnly outside TypedDict in this PEP in order to keep the scope limited, but it’s definitely a reasonable idea, and I would encourage anyone who wants this feature to start exploring how ReadOnly could work in other contexts.

1 Like

@alicederyn, what’s the latest status of PEP 705? If and when you think it’s ready for consideration by the Typing Council, please consider formally submitting it by following these instructions.

1 Like

@Jelle You mentioned wanting this to be released in typing-extensions for some time before making a decision. Should I submit? I don’t believe any further PEP changes are likely.

I think we’re ready.

Wow, the steps involved are MUCH more difficult than they used to be. I need to personally rewrite the typing specifications and create tests? I can’t give an ETA on that.

I feel we don’t necessarily have all that done by the PEP author (though I’m not speaking for the rest of the Typing Council here): it can wait a little, and perhaps be done by others.

The spec changes at least should mostly be a matter of copy-pasting the PEP’s spec section into the right part of the typing spec. That’s how most of the rest of the spec was created, after all.

@alicederyn, don’t worry about writing the typing spec or the tests. That can wait until after the PEP is accepted. As Jelle says, the typing spec can be copied from the PEP’s spec section. And I can help write the conformance tests. (I’ve already written pretty extensive tests in pyright for the PEP 705 functionality.)

I’m unclear what should be in the pull request required in step 2 then

I think step 2 doesn’t apply because you’re submitting a formal PEP. You can skip that step and proceed to 3. (@Jelle , we should probably clarify this in the instructions.)

1 Like

I’m happy to announce that the Typing Council supports this PEP. Statement below, posted on behalf of the full Council:

The Python Typing Council recommends accepting PEP 705, “TypedDict: Read-only items”. The PEP’s motivation and rationale are well written and clearly describe how attribute mutability can hurt ergonomics in common use cases. Variants of the idea have been discussed and iterated on over the last year and a half, and reflect learnings from previous community experience with TypedDict features — for instance, the final version incorporates lessons from PEP 655. We expect PEP 705 to compose well with existing TypedDict features. The type qualifier introduced would likely work well if we extended support to Protocols in the future. The PEP has already been implemented in one type checker and we foresee no major issues in getting it implemented in other type checkers.

8 Likes

The Steering Council has decided to follow the Typing Council’s recommendation and accepts PEP 705: PEP 705 -- TypedDict: Read-only items · Issue #229 · python/steering-council · GitHub

8 Likes

Thank you! I opened issues to track implementing the PEP:

Any help from readers here on either issue would be appreciated.

2 Likes